Compare commits
1 Commits
dev-v2
...
pr@dev-v2@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d15e0106f |
@ -17,10 +17,9 @@ import io.dataease.license.config.XpackInteract;
|
||||
import io.dataease.model.BusiNodeRequest;
|
||||
import io.dataease.model.BusiNodeVO;
|
||||
import io.dataease.operation.manage.CoreOptRecentManage;
|
||||
import io.dataease.utils.AuthUtils;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.CommunityUtils;
|
||||
import io.dataease.utils.TreeUtils;
|
||||
import io.dataease.system.dao.auto.entity.CoreSysSetting;
|
||||
import io.dataease.system.manage.SysParameterManage;
|
||||
import io.dataease.utils.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
@ -43,6 +42,9 @@ public class DataSourceManage {
|
||||
@Resource
|
||||
private CoreOptRecentManage coreOptRecentManage;
|
||||
|
||||
@Resource
|
||||
private SysParameterManage sysParameterManage;
|
||||
|
||||
private DatasourceNodeBO rootNode() {
|
||||
return new DatasourceNodeBO(0L, "root", false, 7, -1L, 0, "mysql");
|
||||
}
|
||||
@ -157,10 +159,20 @@ public class DataSourceManage {
|
||||
}
|
||||
|
||||
|
||||
public void encryptDsConfig(){
|
||||
coreDatasourceMapper.selectList(null).forEach(dataSource -> {
|
||||
coreDatasourceMapper.updateById(dataSource);
|
||||
});
|
||||
public void encryptDsConfig() {
|
||||
List<CoreSysSetting> coreSysSettings = sysParameterManage.groupList("datasource.encrypt");
|
||||
if (CollectionUtils.isEmpty(coreSysSettings)) {
|
||||
coreDatasourceMapper.selectList(null).forEach(dataSource -> {
|
||||
coreDatasourceMapper.updateById(dataSource);
|
||||
});
|
||||
CoreSysSetting coreSysSetting = new CoreSysSetting();
|
||||
coreSysSetting.setId(IDUtils.snowID());
|
||||
coreSysSetting.setPkey("datasource.encrypt");
|
||||
coreSysSetting.setPval("true");
|
||||
coreSysSetting.setType("text");
|
||||
coreSysSetting.setSort(1);
|
||||
sysParameterManage.insert(coreSysSetting);
|
||||
}
|
||||
}
|
||||
|
||||
public DatasourceDTO getDs(Long id) {
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package io.dataease.rmonitor.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PerMonitorCheckBO implements Serializable {
|
||||
|
||||
private boolean valid;
|
||||
|
||||
private boolean emptyPermission;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package io.dataease.rmonitor.bo;
|
||||
|
||||
import io.dataease.model.TreeBaseModel;
|
||||
import io.dataease.model.TreeResultModel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PerMonitorNodeBO implements TreeBaseModel<PerMonitorNodeBO>, TreeResultModel<PerMonitorNodeBO>, Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Long pid;
|
||||
|
||||
private boolean leaf;
|
||||
|
||||
private int extraFlag;
|
||||
|
||||
private List<PerMonitorNodeBO> children;
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
package io.dataease.rmonitor.manage;
|
||||
|
||||
import io.dataease.constant.DataSourceType;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.rmonitor.bo.PerMonitorCheckBO;
|
||||
import io.dataease.rmonitor.bo.PerMonitorNodeBO;
|
||||
import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
|
||||
import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
|
||||
import io.dataease.rmonitor.mapper.entity.DsFreeResource;
|
||||
import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.TreeUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component("resourceMonitorManage")
|
||||
public class ResourceMonitorManage {
|
||||
|
||||
|
||||
@Resource(name = "resourceMonitorSyncManage")
|
||||
private ResourceMonitorSyncManage resourceMonitorSyncManage;
|
||||
|
||||
@Resource
|
||||
private ResourceMonitorMapper resourceMonitorMapper;
|
||||
|
||||
|
||||
private boolean existFreeResource() {
|
||||
int rCount = resourceMonitorMapper.dsCount() + resourceMonitorMapper.datasetCount() + resourceMonitorMapper.vCount();
|
||||
return rCount > 0;
|
||||
}
|
||||
|
||||
private Map<String, List<PerMonitorNodeBO>> freeResource() {
|
||||
Map<String, List<PerMonitorNodeBO>> result = new HashMap<>();
|
||||
|
||||
List<DsFreeResource> dsFreeResources = resourceMonitorMapper.queryFreeDs();
|
||||
if (CollectionUtils.isNotEmpty(dsFreeResources)) {
|
||||
List<PerMonitorNodeBO> dsBos = dsFreeResources.stream().map(node -> {
|
||||
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
|
||||
bo.setLeaf(!StringUtils.equals("folder", node.getType()));
|
||||
bo.setExtraFlag(DataSourceType.valueOf(node.getType()).getFlag());
|
||||
return bo;
|
||||
}).collect(Collectors.toList());
|
||||
List<PerMonitorNodeBO> dsTree = TreeUtils.mergeTree(dsBos, PerMonitorNodeBO.class, false);
|
||||
result.put("datasource", dsTree);
|
||||
}
|
||||
|
||||
List<DatasetFreeResource> datasetFreeResources = resourceMonitorMapper.queryFreeDataset();
|
||||
if (CollectionUtils.isNotEmpty(datasetFreeResources)) {
|
||||
List<PerMonitorNodeBO> datasetBos = datasetFreeResources.stream().map(node -> {
|
||||
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
|
||||
bo.setLeaf(!StringUtils.equals("folder", node.getNodeType()));
|
||||
return bo;
|
||||
}).collect(Collectors.toList());
|
||||
List<PerMonitorNodeBO> datasetTree = TreeUtils.mergeTree(datasetBos, PerMonitorNodeBO.class, false);
|
||||
result.put("dataset", datasetTree);
|
||||
}
|
||||
|
||||
List<VisualFreeResource> visualFreeResources = resourceMonitorMapper.queryFreeVusial();
|
||||
if (CollectionUtils.isNotEmpty(visualFreeResources)) {
|
||||
Map<String, List<VisualFreeResource>> baseMap = visualFreeResources.stream().collect(Collectors.groupingBy(VisualFreeResource::getType));
|
||||
for (Map.Entry<String, List<VisualFreeResource>> entry : baseMap.entrySet()) {
|
||||
List<VisualFreeResource> freeResource = entry.getValue();
|
||||
List<PerMonitorNodeBO> visualBos = freeResource.stream().map(node -> {
|
||||
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
|
||||
bo.setLeaf(!StringUtils.equals("folder", node.getNodeType()));
|
||||
return bo;
|
||||
}).collect(Collectors.toList());
|
||||
result.put(convertBusiFlag(entry.getKey()), TreeUtils.mergeTree(visualBos, PerMonitorNodeBO.class, false));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String convertBusiFlag(String key) {
|
||||
if (StringUtils.equals("dashboard", key)) {
|
||||
return "panel";
|
||||
} else if (StringUtils.equals("dataV", key)) {
|
||||
return "screen";
|
||||
} else return key;
|
||||
}
|
||||
|
||||
public boolean check() {
|
||||
PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
|
||||
return checkBO.isValid() && checkBO.isEmptyPermission() && existFreeResource();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete() {
|
||||
boolean existFree = existFreeResource();
|
||||
if (!existFree) DEException.throwException("无未同步资源!");
|
||||
resourceMonitorMapper.delFreeDs();
|
||||
resourceMonitorMapper.delFreeDataset();
|
||||
resourceMonitorMapper.delFreeVisual();
|
||||
}
|
||||
|
||||
public void sync() {
|
||||
//1、从xpack获取资源 如果xpack不存在 或者资源不为空 则直接返回 并且抛出异常“仅支持首次导入lic同步”
|
||||
//2、从core获取资源
|
||||
//3、根据类型分组 并组织成树形结构
|
||||
//4、分别遍历每一棵树 从上到下 同步到权限体系 给默认组织
|
||||
PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
|
||||
if (!checkBO.isValid()) DEException.throwException("缺少许可证");
|
||||
if (!checkBO.isEmptyPermission()) DEException.throwException("仅支持license首次导入同步");
|
||||
Map<String, List<PerMonitorNodeBO>> freeResourceMap = freeResource();
|
||||
if (MapUtils.isEmpty(freeResourceMap)) DEException.throwException("无未同步资源!");
|
||||
for (Map.Entry<String, List<PerMonitorNodeBO>> entry : freeResourceMap.entrySet()) {
|
||||
resourceMonitorSyncManage.sync(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package io.dataease.rmonitor.manage;
|
||||
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import io.dataease.rmonitor.bo.PerMonitorCheckBO;
|
||||
import io.dataease.rmonitor.bo.PerMonitorNodeBO;
|
||||
import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component("resourceMonitorSyncManage")
|
||||
public class ResourceMonitorSyncManage {
|
||||
|
||||
@Resource(name = "resourceMonitorMapper")
|
||||
private ResourceMonitorMapper resourceMonitorMapper;
|
||||
|
||||
@XpackInteract(value = "resourceMonitorSyncManage", replace = true)
|
||||
public void sync(String flag, List<PerMonitorNodeBO> treeNodes) {
|
||||
DEException.throwException("缺失许可证");
|
||||
}
|
||||
|
||||
@XpackInteract(value = "resourceMonitorSyncManage", replace = true)
|
||||
public PerMonitorCheckBO checkXpackResource() {
|
||||
return new PerMonitorCheckBO();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package io.dataease.rmonitor.mapper;
|
||||
|
||||
import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
|
||||
import io.dataease.rmonitor.mapper.entity.DsFreeResource;
|
||||
import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ResourceMonitorMapper {
|
||||
|
||||
@Select("select count(id) from core_datasource")
|
||||
int dsCount();
|
||||
|
||||
@Select("select count(id) from core_dataset_group")
|
||||
int datasetCount();
|
||||
|
||||
@Select("select count(id) from data_visualization_info where delete_flag = 0 and pid != -1")
|
||||
int vCount();
|
||||
|
||||
@Select("select id, name, pid, type, status from core_datasource")
|
||||
List<DsFreeResource> queryFreeDs();
|
||||
|
||||
@Select("select id, name, pid, node_type from core_dataset_group")
|
||||
List<DatasetFreeResource> queryFreeDataset();
|
||||
|
||||
@Select("select id, name, pid, node_type, type from data_visualization_info where delete_flag = 0 and pid != -1")
|
||||
List<VisualFreeResource> queryFreeVusial();
|
||||
|
||||
@Delete("delete from core_datasource")
|
||||
void delFreeDs();
|
||||
|
||||
@Delete("delete from core_dataset_group")
|
||||
void delFreeDataset();
|
||||
@Delete("delete from data_visualization_info")
|
||||
void delFreeVisual();
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package io.dataease.rmonitor.mapper.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class BaseFreeResource implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Long pid;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package io.dataease.rmonitor.mapper.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class DatasetFreeResource extends BaseFreeResource implements Serializable {
|
||||
|
||||
private String nodeType;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package io.dataease.rmonitor.mapper.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class DsFreeResource extends BaseFreeResource implements Serializable {
|
||||
|
||||
private String type;
|
||||
|
||||
private String status;
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package io.dataease.rmonitor.mapper.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class VisualFreeResource extends BaseFreeResource implements Serializable {
|
||||
|
||||
private String nodeType;
|
||||
|
||||
private String type;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package io.dataease.rmonitor.server;
|
||||
|
||||
import io.dataease.api.rmonitor.ResourceMonitorApi;
|
||||
import io.dataease.rmonitor.manage.ResourceMonitorManage;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/rmonitor")
|
||||
public class ResourceMonitorServer implements ResourceMonitorApi {
|
||||
|
||||
@Resource(name = "resourceMonitorManage")
|
||||
private ResourceMonitorManage resourceMonitorManage;
|
||||
|
||||
@Override
|
||||
public boolean existFree() {
|
||||
return resourceMonitorManage.check();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
resourceMonitorManage.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() {
|
||||
resourceMonitorManage.sync();
|
||||
}
|
||||
}
|
||||
@ -172,4 +172,9 @@ public class SysParameterManage {
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
public void insert(CoreSysSetting coreSysSetting) {
|
||||
coreSysSettingMapper.insert(coreSysSetting);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -52,6 +52,3 @@ create table core_custom_geo_sub_area
|
||||
)
|
||||
comment '自定义地理区域分区详情';
|
||||
|
||||
|
||||
UPDATE `core_sys_setting` SET `sort` = 11 WHERE `pkey` = 'basic.dsIntervalTime';
|
||||
|
||||
|
||||
@ -3,3 +3,7 @@ import request from '@/config/axios'
|
||||
export const validateApi = data => request.post({ url: '/license/validate', data })
|
||||
export const buildVersionApi = () => request.get({ url: '/license/version' })
|
||||
export const updateInfoApi = data => request.post({ url: '/license/update', data })
|
||||
|
||||
export const checkFreeApi = () => request.get({ url: '/rmonitor/existFree' })
|
||||
export const syncFreeApi = () => request.post({ url: '/rmonitor/sync' })
|
||||
export const delFreeApi = () => request.post({ url: '/rmonitor/delete' })
|
||||
|
||||
@ -139,7 +139,8 @@ const previewOuter = () => {
|
||||
}
|
||||
canvasSave(() => {
|
||||
const url = '#/preview?dvId=' + dvInfo.value.id + '&ignoreParams=true'
|
||||
const newWindow = window.open(url, '_blank')
|
||||
const openType = wsCache.get('open-backend') === '1' ? '_self' : '_blank'
|
||||
const newWindow = window.open(url, openType)
|
||||
initOpenHandler(newWindow)
|
||||
})
|
||||
}
|
||||
|
||||
@ -195,11 +195,7 @@
|
||||
:disabled="canvasStyleData.dashboard.resultMode === 'all'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="dvInfo.type === 'dashboard'"
|
||||
style="margin-top: 16px; margin-bottom: 8px"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-form-item style="margin-top: 16px; margin-bottom: 8px" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
:effect="themes"
|
||||
size="small"
|
||||
@ -210,7 +206,7 @@
|
||||
<span style="margin-right: 4px"> {{ t('visualization.button_tips') }}</span>
|
||||
<el-tooltip class="item" :effect="toolTip" placement="bottom">
|
||||
<template #content>
|
||||
<div>{{ t('visualization.effective_during_link') }}</div>
|
||||
<div>{{ t('visualization.effective_during_preview') }}</div>
|
||||
</template>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>
|
||||
@ -219,11 +215,7 @@
|
||||
</span>
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="dvInfo.type === 'dashboard'"
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
:effect="themes"
|
||||
size="small"
|
||||
@ -249,7 +241,7 @@ import {
|
||||
LIGHT_THEME_DASHBOARD_BACKGROUND
|
||||
} from '@/utils/canvasStyle'
|
||||
import {
|
||||
CHART_FONT_FAMILY_ORIGIN,
|
||||
CHART_FONT_FAMILY,
|
||||
DEFAULT_COLOR_CASE_DARK,
|
||||
DEFAULT_COLOR_CASE_LIGHT,
|
||||
DEFAULT_TAB_COLOR_CASE_DARK,
|
||||
@ -282,7 +274,7 @@ const props = defineProps({
|
||||
default: 'light'
|
||||
}
|
||||
})
|
||||
const fontFamily = CHART_FONT_FAMILY_ORIGIN.concat(
|
||||
const fontFamily = CHART_FONT_FAMILY.concat(
|
||||
appearanceStore.fontList.map(ele => ({
|
||||
name: ele.name,
|
||||
value: ele.name
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<el-color-picker
|
||||
:effect="themes"
|
||||
v-model="seniorStyleSetting.linkageIconColor"
|
||||
:trigger-width="100"
|
||||
:trigger-width="197"
|
||||
is-custom
|
||||
:predefine="state.predefineColors"
|
||||
@change="themeChange"
|
||||
@ -30,7 +30,7 @@
|
||||
<el-color-picker
|
||||
v-model="seniorStyleSetting.drillLayerColor"
|
||||
:effect="themes"
|
||||
:trigger-width="100"
|
||||
:trigger-width="197"
|
||||
is-custom
|
||||
:predefine="state.predefineColors"
|
||||
@change="themeChange"
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<path
|
||||
:d="smallGridPathD"
|
||||
fill="none"
|
||||
stroke="rgba(207, 207, 207, 0.4)"
|
||||
stroke="rgba(207, 207, 207, 0.3)"
|
||||
stroke-width="0.8"
|
||||
/>
|
||||
</pattern>
|
||||
@ -21,11 +21,11 @@
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<rect :width="middleGridW" :height="middleGridH" fill="url(#smallGrid)" />
|
||||
<path :d="middleGridPathD" fill="none" stroke="rgba(207, 207, 207, 0.4)" stroke-width="1" />
|
||||
<path :d="middleGridPathD" fill="none" stroke="rgba(207, 207, 207, 0.3)" stroke-width="1" />
|
||||
</pattern>
|
||||
<pattern id="grid" :width="gridW" :height="gridH" patternUnits="userSpaceOnUse">
|
||||
<rect :width="gridW" :height="gridH" fill="url(#middleGrid)" />
|
||||
<path :d="pathD" fill="none" stroke="rgba(207, 207, 207, 0.4)" stroke-width="1.2" />
|
||||
<path :d="pathD" fill="none" stroke="rgba(207, 207, 207, 0.3)" stroke-width="1.2" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#grid)" />
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<defs>
|
||||
<pattern id="grid" :width="gridW" :height="gridH" patternUnits="userSpaceOnUse">
|
||||
<rect :width="gridW" :height="gridH" fill="url(#middleGrid)" />
|
||||
<path :d="pathD" fill="none" stroke="rgba(207, 207, 207, 0.4)" stroke-width="0.7" />
|
||||
<path :d="pathD" fill="none" stroke="rgba(207, 207, 207, 0.2)" stroke-width="0.5" />
|
||||
</pattern>
|
||||
<pattern
|
||||
id="middleGrid"
|
||||
@ -15,7 +15,7 @@
|
||||
<path
|
||||
:d="middleGridPathD"
|
||||
fill="none"
|
||||
stroke="rgba(207, 207, 207, 0.4)"
|
||||
stroke="rgba(207, 207, 207, 0.2)"
|
||||
stroke-width="0.3"
|
||||
/>
|
||||
</pattern>
|
||||
|
||||
@ -74,6 +74,14 @@ const closeEditComponentName = () => {
|
||||
|
||||
const dragOnEnd = ({ oldIndex, newIndex }) => {
|
||||
const source = componentData.value[newIndex]
|
||||
const comLength = componentData.value.length
|
||||
// 还原数组
|
||||
componentData.value.splice(newIndex, 1)
|
||||
componentData.value.splice(oldIndex, 0, source)
|
||||
const target = componentData.value[comLength - 1 - oldIndex]
|
||||
// 反向移动数组
|
||||
componentData.value.splice(comLength - 1 - oldIndex, 1)
|
||||
componentData.value.splice(comLength - 1 - newIndex, 0, target)
|
||||
dvMainStore.setCurTabName(source.title)
|
||||
eventBus.emit('onTabSortChange-' + tabElement.value?.id)
|
||||
snapshotStore.recordSnapshotCache()
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<div class="bar-content">
|
||||
<div class="bar-diver" />
|
||||
<div v-show="fromLink" class="link-icon-active">
|
||||
<el-tooltip :content="t('visualization.back_parent')">
|
||||
<el-tooltip content="返回上一级">
|
||||
<el-icon style="width: 16px; height: 16px" @click="back2Last">
|
||||
<Icon name="icon_left_outlined">
|
||||
<icon_left_outlined class="svg-icon" />
|
||||
@ -34,7 +34,7 @@
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="link-icon-active">
|
||||
<el-tooltip :content="t('visualization.export_pdf')">
|
||||
<el-tooltip content="导出PDF">
|
||||
<el-icon style="width: 16px; height: 16px" @click="exportPDF">
|
||||
<Icon name="icon_download_outlined">
|
||||
<icon_download_outlined class="svg-icon" />
|
||||
@ -43,11 +43,7 @@
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div id="fullscreenElement" class="link-icon-active" style="padding-right: 4px">
|
||||
<el-tooltip
|
||||
:content="
|
||||
fullscreenFlag ? t('visualization.ext_fullscreen') : t('visualization.fullscreen')
|
||||
"
|
||||
>
|
||||
<el-tooltip :content="fullscreenFlag ? '退出全屏' : '全屏'">
|
||||
<el-icon style="width: 16px; height: 16px" @click="toggleFullscreen">
|
||||
<Icon name="icon_minify_outlined" v-if="fullscreenFlag">
|
||||
<icon_minify_outlined class="svg-icon" />
|
||||
@ -76,7 +72,6 @@ import icon_magnify_outlined from '@/assets/svg/icon_magnify_outlined.svg'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const props = defineProps({
|
||||
canvasStyleData: {
|
||||
@ -87,7 +82,6 @@ const props = defineProps({
|
||||
|
||||
const { canvasStyleData } = toRefs(props)
|
||||
const { fullscreenFlag } = storeToRefs(dvMainStore)
|
||||
const { t } = useI18n()
|
||||
|
||||
const state = reactive({
|
||||
fullscreenElement: null,
|
||||
@ -128,7 +122,7 @@ const back2Last = () => {
|
||||
window.location.reload()
|
||||
}
|
||||
const exportPDF = () => {
|
||||
useEmitt().emitter.emit('canvasDownload', 'pdf')
|
||||
useEmitt().emitter.emit('canvasDownload')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('visualization.description')" prop="description">
|
||||
<el-input
|
||||
:placeholder="t('commons.input_content')"
|
||||
:placeholder="t('visualization.input_content')"
|
||||
show-word-limit
|
||||
v-model="state.form.description"
|
||||
type="textarea"
|
||||
@ -44,7 +44,7 @@
|
||||
<template #footer>
|
||||
<div class="apply" style="width: 100%">
|
||||
<el-button secondary @click="close">{{ t('commons.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="downloadApp">{{ t('chart.export') }}</el-button>
|
||||
<el-button type="primary" @click="downloadApp">{{ t('visualization.export') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
@ -3,7 +3,6 @@ import noLic from './nolic.vue'
|
||||
import { ref, useAttrs, onMounted } from 'vue'
|
||||
import { execute, randomKey, formatArray } from './convert'
|
||||
import { load, loadDistributed, xpackModelApi } from '@/api/plugin'
|
||||
import configGlobal from '@/components/config-global/src/ConfigGlobal.vue'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { i18n } from '@/plugins/vue-i18n'
|
||||
import * as Vue from 'vue'
|
||||
@ -153,13 +152,13 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<configGlobal>
|
||||
<component
|
||||
:key="attrs.jsname"
|
||||
ref="pluginProxy"
|
||||
:is="plugin"
|
||||
v-loading="loading"
|
||||
v-bind="attrs"
|
||||
></component>
|
||||
</configGlobal>
|
||||
<component
|
||||
:key="attrs.jsname"
|
||||
ref="pluginProxy"
|
||||
:is="plugin"
|
||||
v-loading="loading"
|
||||
v-bind="attrs"
|
||||
></component>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
<span style="margin-right: 4px">{{ t('visualization.show_zoom_button') }}</span>
|
||||
<el-tooltip class="item" :effect="themes" placement="bottom">
|
||||
<template #content>
|
||||
<div>{{ t('visualization.effective_during_link') }}</div>
|
||||
<div>{{ t('visualization.effective_during_preview') }}</div>
|
||||
</template>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>
|
||||
@ -83,7 +83,7 @@ import { storeToRefs } from 'pinia'
|
||||
import { ElFormItem, ElIcon } from 'element-plus-secondary'
|
||||
import Icon from '../icon-custom/src/Icon.vue'
|
||||
import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
|
||||
import { CHART_FONT_FAMILY_ORIGIN } from '@/views/chart/components/editor/util/chart'
|
||||
import { CHART_FONT_FAMILY } from '@/views/chart/components/editor/util/chart'
|
||||
import { adaptTitleFontFamilyAll } from '@/utils/canvasStyle'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
@ -91,7 +91,7 @@ const { t } = useI18n()
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { canvasStyleData } = storeToRefs(dvMainStore)
|
||||
const appearanceStore = useAppearanceStoreWithOut()
|
||||
const fontFamily = CHART_FONT_FAMILY_ORIGIN.concat(
|
||||
const fontFamily = CHART_FONT_FAMILY.concat(
|
||||
appearanceStore.fontList.map(ele => ({
|
||||
name: ele.name,
|
||||
value: ele.name
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
placement="top"
|
||||
:content="t('visualization.sort')"
|
||||
:content="'排序'"
|
||||
v-if="element.component === 'DeTabs' && showPosition === 'canvas'"
|
||||
>
|
||||
<el-icon class="bar-base-icon" @click="tabSort">
|
||||
@ -21,12 +21,12 @@
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<template v-if="element.component === 'VQuery' && showPosition === 'canvas'">
|
||||
<span :title="t('visualization.add_query_filter')">
|
||||
<span title="添加查询条件">
|
||||
<el-icon class="bar-base-icon" @click="addQueryCriteria">
|
||||
<Icon name="icon_add_outlined"><icon_add_outlined class="svg-icon" /></Icon
|
||||
></el-icon>
|
||||
</span>
|
||||
<span :title="t('visualization.edit_query_filter')">
|
||||
<span title="编辑查询条件">
|
||||
<el-icon class="bar-base-icon" @click="editQueryCriteria">
|
||||
<Icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></Icon
|
||||
></el-icon>
|
||||
@ -47,7 +47,7 @@
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:placement="showBarTooltipPosition"
|
||||
:content="t('visualization.show_data')"
|
||||
content="查看数据"
|
||||
v-if="!['picture-group', 'rich-text'].includes(element.innerType) && barShowCheck('details')"
|
||||
>
|
||||
<span>
|
||||
@ -59,7 +59,7 @@
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
placement="top"
|
||||
:content="t('visualization.input_calc_data')"
|
||||
content="输入计算数据"
|
||||
v-if="barShowCheck('datasetParams') && datasetParamsSetShow"
|
||||
>
|
||||
<span>
|
||||
@ -102,14 +102,14 @@
|
||||
</el-icon>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu style="width: 158px">
|
||||
<el-dropdown-item @click="copyComponent" v-if="barShowCheck('copy')">{{
|
||||
t('visualization.copy')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item @click="copyComponent" v-if="barShowCheck('copy')"
|
||||
>复制</el-dropdown-item
|
||||
>
|
||||
<template v-if="element.innerType !== 'rich-text' && barShowCheck('enlarge')">
|
||||
<el-dropdown-item
|
||||
:divided="showPosition === 'canvas'"
|
||||
@click="userViewEnlargeOpen($event, 'enlarge')"
|
||||
>{{ t('visualization.enlarge') }}</el-dropdown-item
|
||||
>放大</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
@click="userViewEnlargeOpen($event, 'details')"
|
||||
@ -117,7 +117,7 @@
|
||||
!['picture-group', 'rich-text'].includes(element.innerType) &&
|
||||
barShowCheck('details')
|
||||
"
|
||||
>{{ t('visualization.show_data') }}</el-dropdown-item
|
||||
>查看数据</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
style="padding: 0"
|
||||
@ -134,7 +134,7 @@
|
||||
class="flex-align-center"
|
||||
style="width: 100%; padding: 5px 6px 5px 16px; line-height: 24px"
|
||||
>
|
||||
{{ t('visualization.export_as') }}
|
||||
导出为
|
||||
<el-icon size="16px" style="margin-left: auto"><ArrowRight /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
@ -146,11 +146,11 @@
|
||||
v-if="exportPermissions[1] && element.innerType === 'table-pivot'"
|
||||
@click="exportAsFormattedExcel"
|
||||
>
|
||||
<span>{{ t('visualization.excel_with_format') }}</span>
|
||||
<span>Excel(带格式)</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="exportPermissions[0]" @click="exportAsImage">{{
|
||||
t('visualization.image')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item v-if="exportPermissions[0]" @click="exportAsImage"
|
||||
>图片</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@ -161,9 +161,9 @@
|
||||
jsname="L2NvbXBvbmVudC90aHJlc2hvbGQtd2FybmluZy9FZGl0QmFySGFuZGxlcg=="
|
||||
@close-item="closeItem"
|
||||
/>
|
||||
<el-dropdown-item divided @click="deleteComponent" v-if="barShowCheck('delete')">{{
|
||||
t('visualization.delete')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="deleteComponent" v-if="barShowCheck('delete')"
|
||||
>删除</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@ -191,11 +191,11 @@
|
||||
v-if="exportPermissions[1] && element.innerType === 'table-pivot'"
|
||||
@click="exportAsFormattedExcel"
|
||||
>
|
||||
<span>{{ t('visualization.excel_with_format') }}</span>
|
||||
<span>Excel(带格式)</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="exportPermissions[0]" @click="exportAsImage">{{
|
||||
t('visualization.image')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item v-if="exportPermissions[0]" @click="exportAsImage"
|
||||
>图片</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
@ -15,7 +15,7 @@ import { useLinkStoreWithOut } from '@/store/modules/link'
|
||||
import { config } from './config'
|
||||
import { configHandler } from './refresh'
|
||||
import { isMobile } from '@/utils/utils'
|
||||
import { useRequestStoreWithOut } from '@/store/modules/request'
|
||||
|
||||
type AxiosErrorWidthLoading<T> = T & {
|
||||
config: {
|
||||
loading?: boolean
|
||||
@ -31,11 +31,8 @@ import router from '@/router'
|
||||
|
||||
const { result_code } = config
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const { wsCache } = useCache()
|
||||
const requestStore = useRequestStoreWithOut()
|
||||
const embeddedStore = useEmbedded()
|
||||
const basePath = import.meta.env.VITE_API_BASEPATH
|
||||
|
||||
@ -206,15 +203,6 @@ service.interceptors.response.use(
|
||||
}
|
||||
},
|
||||
(error: AxiosErrorWidthLoading<AxiosError>) => {
|
||||
if (error.message?.includes('timeout of')) {
|
||||
requestStore.resetLoadingMap()
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '请求超时,请稍后再试',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
|
||||
if (!error?.response) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ const handleDragEnd = e => {
|
||||
<drag-component
|
||||
:themes="themes"
|
||||
:icon="dbMoreWeb"
|
||||
:label="$t('visualization.web')"
|
||||
label="网页"
|
||||
drag-info="DeFrame&DeFrame"
|
||||
></drag-component>
|
||||
</div>
|
||||
|
||||
@ -580,7 +580,8 @@ const list = [
|
||||
color: '',
|
||||
padding: 4,
|
||||
verticalAlign: 'middle',
|
||||
scrollSpeed: 0
|
||||
scrollSpeed: 0,
|
||||
fontFamily: 'Microsoft YaHei'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
<template>
|
||||
<div class="pic-main">
|
||||
<chart-error v-if="isError" :err-msg="errMsg" />
|
||||
<img
|
||||
draggable="false"
|
||||
v-else-if="state.showUrl"
|
||||
v-if="state.showUrl"
|
||||
:style="imageAdapter"
|
||||
:src="imgUrlTrans(state.showUrl)"
|
||||
/>
|
||||
<template v-else>
|
||||
<chart-empty-info :view-icon="view.type"></chart-empty-info>
|
||||
<chart-empty-info
|
||||
:themes="canvasStyleData.dashboard.themeColor"
|
||||
:view-icon="view.type"
|
||||
></chart-empty-info>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@ -33,7 +35,6 @@ import { parseJson } from '@/views/chart/components/js/util'
|
||||
import { mappingColor } from '@/views/chart/components/js/panel/common/common_table'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import ChartEmptyInfo from '@/views/chart/components/views/components/ChartEmptyInfo.vue'
|
||||
import ChartError from '@/views/chart/components/views/components/ChartError.vue'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { canvasViewInfo, editMode, mobileInPc, canvasStyleData } = storeToRefs(dvMainStore)
|
||||
const state = reactive({
|
||||
@ -201,17 +202,12 @@ const calcData = (viewCalc: Chart, callback) => {
|
||||
}
|
||||
if (viewCalc.tableId || viewCalc['dataFrom'] === 'template') {
|
||||
const v = JSON.parse(JSON.stringify(viewCalc))
|
||||
v.type = 'table-info'
|
||||
v.render = 'antv'
|
||||
v.resultCount = 1
|
||||
getData(v)
|
||||
.then(res => {
|
||||
if (res.code && res.code !== 0) {
|
||||
isError.value = true
|
||||
errMsg.value = res.msg
|
||||
} else {
|
||||
res.type = 'picture-group'
|
||||
res.render = 'custom'
|
||||
state.data = res?.data
|
||||
state.viewDataInfo = res
|
||||
state.totalItems = res?.totalItems
|
||||
|
||||
@ -62,7 +62,7 @@ import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { parseJson } from '@/views/chart/components/js/util'
|
||||
import { mappingColor } from '@/views/chart/components/js/panel/common/common_table'
|
||||
import { CHART_FONT_FAMILY_ORIGIN } from '@/views/chart/components/editor/util/chart'
|
||||
import { CHART_FONT_FAMILY } from '@/views/chart/components/editor/util/chart'
|
||||
import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const errMsg = ref('')
|
||||
@ -137,7 +137,7 @@ const myValue = ref('')
|
||||
const systemFontFamily = appearanceStore.fontList.map(item => item.name)
|
||||
const curFontFamily = () => {
|
||||
let result = ''
|
||||
CHART_FONT_FAMILY_ORIGIN.concat(
|
||||
CHART_FONT_FAMILY.concat(
|
||||
appearanceStore.fontList.map(ele => ({
|
||||
name: ele.name,
|
||||
value: ele.name
|
||||
@ -225,7 +225,7 @@ const init = ref({
|
||||
// 显示原始手柄并移除克隆手柄
|
||||
originalHandle.style.display = ''
|
||||
if (cloneHandle) {
|
||||
cloneHandle.parentNode?.removeChild(cloneHandle) // 获取原手柄的父元素
|
||||
cloneHandle.parentNode.removeChild(cloneHandle) // 获取原手柄的父元素
|
||||
}
|
||||
cloneHandle = null
|
||||
originalHandle = null
|
||||
@ -539,9 +539,6 @@ const calcData = (view: Chart, callback) => {
|
||||
updateEmptyValue(view)
|
||||
if (view.tableId || view['dataFrom'] === 'template') {
|
||||
const v = JSON.parse(JSON.stringify(view))
|
||||
v.type = 'table-info'
|
||||
v.render = 'antv'
|
||||
v.resultCount = 1
|
||||
getData(v)
|
||||
.then(res => {
|
||||
if (res.code && res.code !== 0) {
|
||||
@ -549,8 +546,6 @@ const calcData = (view: Chart, callback) => {
|
||||
errMsg.value = res.msg
|
||||
} else {
|
||||
state.data = res?.data
|
||||
res.type = 'rich-text'
|
||||
res.render = 'custom'
|
||||
state.viewDataInfo = res
|
||||
state.totalItems = res?.totalItems
|
||||
const curViewInfo = canvasViewInfo.value[element.value.id]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, toRefs, PropType } from 'vue'
|
||||
import { computed, toRefs, PropType, CSSProperties } from 'vue'
|
||||
import Chart from '@/views/chart/components/views/index.vue'
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@ -268,13 +268,7 @@ const disabledDate = val => {
|
||||
.startOf(queryTimeType.value)
|
||||
.valueOf() -
|
||||
1000 <
|
||||
timeStamp ||
|
||||
dayjs(startWindowTime.value)
|
||||
.subtract(maximumSingleQuery, queryTimeType.value)
|
||||
.startOf(queryTimeType.value)
|
||||
.valueOf() +
|
||||
1000 >
|
||||
timeStamp
|
||||
timeStamp
|
||||
}
|
||||
if (intervalType === 'none') {
|
||||
if (dynamicWindow) return isDynamicWindowTime
|
||||
|
||||
@ -1,117 +1,21 @@
|
||||
<script lang="ts" setup>
|
||||
import iconSetting from '@/assets/svg/icon-setting.svg'
|
||||
import TopDocCard from '@/layout/components/TopDocCard.vue'
|
||||
import copilot from '@/assets/svg/copilot.svg'
|
||||
import LangSelector from '@/layout/components/LangSelector.vue'
|
||||
import topEnterpriseTrial from '@/assets/svg/top-enterprise-trial.svg'
|
||||
import topHelpDoc from '@/assets/svg/top-help-doc.svg'
|
||||
import topProductBbs from '@/assets/svg/top-product-bbs.svg'
|
||||
import topTechnology from '@/assets/svg/top-technology.svg'
|
||||
import { useRouter } from 'vue-router'
|
||||
import TopDesktopCard from './TopDesktopCard.vue'
|
||||
import icon_right_outlined from '@/assets/svg/icon_right_outlined.svg'
|
||||
import dvAi from '@/assets/svg/dv-ai.svg'
|
||||
import AiComponent from '@/layout/components/AiComponent.vue'
|
||||
import dvPreviewDownload from '@/assets/svg/dv-preview-download.svg'
|
||||
import ToolboxCfg from './ToolboxCfg.vue'
|
||||
import { findBaseParams } from '@/api/aiComponent'
|
||||
import icon_more_outlined from '@/assets/svg/icon_more_outlined.svg'
|
||||
import msgNotice from '@/assets/svg/msg-notice.svg'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
|
||||
import { msgCountApi } from '@/api/msg'
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const aiBaseUrl = ref('https://maxkb.fit2cloud.com/ui/chat/2ddd8b594ce09dbb?mode=embed')
|
||||
const showToolbox = ref(false)
|
||||
|
||||
const badgeCount = ref('0')
|
||||
const permissionStore = usePermissionStore()
|
||||
const appearanceStore = useAppearanceStoreWithOut()
|
||||
const navigateBg = computed(() => appearanceStore.getNavigateBg)
|
||||
const help = computed(() => appearanceStore.getHelp)
|
||||
const cardInfoList = [
|
||||
{ name: '帮助文档', url: help.value || 'https://dataease.io/docs/v2/', icon: topHelpDoc },
|
||||
{ name: '产品论坛', url: 'https://bbs.fit2cloud.com/c/de/6', icon: topProductBbs },
|
||||
{
|
||||
name: '技术博客',
|
||||
url: 'https://blog.fit2cloud.com/categories/dataease',
|
||||
icon: topTechnology
|
||||
},
|
||||
{ name: '企业版试用', url: 'https://jinshuju.net/f/TK5TTd', icon: topEnterpriseTrial }
|
||||
]
|
||||
const { push, resolve } = useRouter()
|
||||
const redirectUser = () => {
|
||||
const sysMenu = resolve('/sys-setting')
|
||||
const kidPath = sysMenu.matched[0].children[0].path
|
||||
push(`${sysMenu.path}/${kidPath}`)
|
||||
}
|
||||
const msgNoticePush = () => {
|
||||
push('/msg/msg-fill')
|
||||
}
|
||||
const initShowToolbox = () => {
|
||||
showToolbox.value = permissionStore.getRouters.some(route => route.path === '/toolbox')
|
||||
}
|
||||
const downloadClick = params => {
|
||||
useEmitt().emitter.emit('data-export-center', params)
|
||||
}
|
||||
const initAiBase = async () => {
|
||||
await findBaseParams().then(rsp => {
|
||||
const params = rsp.data
|
||||
if (params && params['ai.baseUrl']) {
|
||||
aiBaseUrl.value = params['ai.baseUrl']
|
||||
} else {
|
||||
aiBaseUrl.value = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleCopilotClick = () => {
|
||||
push('/copilot/index')
|
||||
}
|
||||
|
||||
const handleAiClick = () => {
|
||||
useEmitt().emitter.emit('aiComponentChange')
|
||||
}
|
||||
onMounted(() => {
|
||||
initShowToolbox()
|
||||
initAiBase()
|
||||
msgCountApi().then(res => {
|
||||
badgeCount.value = (res?.data > 99 ? '99+' : res?.data) || '0'
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ToolboxCfg v-if="showToolbox" />
|
||||
<el-tooltip effect="dark" :content="$t('data_export.export_center')" placement="bottom">
|
||||
<el-icon
|
||||
style="margin-left: 10px"
|
||||
class="preview-download_icon"
|
||||
:class="navigateBg === 'light' && 'is-light-setting'"
|
||||
>
|
||||
<Icon><dvPreviewDownload @click="downloadClick" class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="$t('v_query.msg_center')" placement="bottom">
|
||||
<el-badge
|
||||
style="margin-left: 10px"
|
||||
:hidden="[0, '0'].includes(badgeCount)"
|
||||
:value="badgeCount"
|
||||
class="ed-badge_custom"
|
||||
>
|
||||
<el-icon class="preview-download_icon" :class="navigateBg === 'light' && 'is-light-setting'">
|
||||
<Icon><msgNotice @click="msgNoticePush" class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-badge>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
:content="$t('commons.system_setting')"
|
||||
placement="top"
|
||||
>
|
||||
<el-tooltip class="box-item" effect="dark" content="系统设置" placement="top">
|
||||
<div
|
||||
class="sys-setting in-iframe-setting"
|
||||
:class="{
|
||||
@ -119,90 +23,12 @@ onMounted(() => {
|
||||
}"
|
||||
>
|
||||
<el-icon @click="redirectUser">
|
||||
<Icon><iconSetting class="svg-icon icon-setting" /></Icon>
|
||||
<Icon class="icon-setting" name="icon-setting"
|
||||
><iconSetting class="svg-icon icon-setting"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
<el-popover
|
||||
popper-class="popper-class_ai-copilot"
|
||||
placement="bottom-end"
|
||||
:width="224"
|
||||
trigger="hover"
|
||||
>
|
||||
<template #default>
|
||||
<div>
|
||||
<div class="card-content_desk">
|
||||
<TopDesktopCard
|
||||
v-if="aiBaseUrl && appearanceStore.getShowAi"
|
||||
@openBlank="handleAiClick"
|
||||
:cardInfo="{
|
||||
icon: dvAi,
|
||||
name: $t('commons.assistant')
|
||||
}"
|
||||
></TopDesktopCard>
|
||||
<TopDesktopCard
|
||||
v-if="appearanceStore.getShowCopilot"
|
||||
@openBlank="handleCopilotClick"
|
||||
:cardInfo="{
|
||||
icon: copilot,
|
||||
name: 'Copilot'
|
||||
}"
|
||||
></TopDesktopCard>
|
||||
</div>
|
||||
<div class="border-top">
|
||||
<el-popover
|
||||
:teleported="false"
|
||||
popper-class="popper-class_ai-copilot"
|
||||
placement="left-start"
|
||||
:width="224"
|
||||
trigger="click"
|
||||
><template #default>
|
||||
<div style="display: flex; padding: 8px; flex-wrap: wrap">
|
||||
<top-doc-card
|
||||
:span="12"
|
||||
v-for="(item, index) in cardInfoList"
|
||||
:key="index"
|
||||
:card-info="item"
|
||||
></top-doc-card>
|
||||
</div>
|
||||
</template>
|
||||
<template #reference
|
||||
><div class="item-select_info">
|
||||
{{ $t('commons.help_center') }}
|
||||
<el-icon style="font-size: 16px">
|
||||
<Icon><icon_right_outlined></icon_right_outlined></Icon>
|
||||
</el-icon></div></template
|
||||
></el-popover>
|
||||
<el-popover
|
||||
:teleported="false"
|
||||
popper-class="popper-class_ai-copilot"
|
||||
placement="left-start"
|
||||
:width="224"
|
||||
trigger="click"
|
||||
><template #default>
|
||||
<div style="padding: 8px 0">
|
||||
<LangSelector />
|
||||
</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<div class="item-select_info">
|
||||
{{ $t('commons.language') }}
|
||||
<el-icon style="font-size: 16px">
|
||||
<Icon><icon_right_outlined></icon_right_outlined></Icon>
|
||||
</el-icon>
|
||||
</div> </template
|
||||
></el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<el-icon class="preview-download_icon" :class="navigateBg === 'light' && 'is-light-setting'">
|
||||
<Icon><icon_more_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
<ai-component v-if="aiBaseUrl && appearanceStore.getShowAi" :base-url="aiBaseUrl"></ai-component>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -226,52 +52,4 @@ onMounted(() => {
|
||||
background-color: #1f23291a !important;
|
||||
}
|
||||
}
|
||||
.preview-download_icon {
|
||||
padding: 5px;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #1e2738;
|
||||
}
|
||||
&.is-light-setting {
|
||||
&:hover {
|
||||
background-color: var(--ed-menu-hover-bg-color) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.popper-class_ai-copilot {
|
||||
padding: 0 !important;
|
||||
|
||||
.card-content_desk {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 12px 12px 8px;
|
||||
}
|
||||
.border-top {
|
||||
border-top: 1px solid #1f232926;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.item-select_info {
|
||||
cursor: pointer;
|
||||
height: 40px;
|
||||
padding: 9px 11px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #1f2329;
|
||||
.ed-icon {
|
||||
color: #8f959e;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #1f23291a;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -62,7 +62,7 @@ const routers: any[] = formatRoute(permissionStore.getRoutersNotHidden as AppCus
|
||||
const showSystem = ref(false)
|
||||
const showToolbox = ref(false)
|
||||
const showOverlay = ref(false)
|
||||
const showOverlayCopilot = ref(false)
|
||||
const showOverlayCopilot = ref(true)
|
||||
const handleSelect = (index: string) => {
|
||||
// 自定义事件
|
||||
if (isExternal(index)) {
|
||||
@ -100,11 +100,11 @@ const initAiBase = async () => {
|
||||
|
||||
const initCopilotBase = async () => {
|
||||
const aiCopilotCheck = wsCache.get('DE-COPILOT-TIPS-CHECK')
|
||||
// if (aiCopilotCheck === 'CHECKED') {
|
||||
// showOverlayCopilot.value = false
|
||||
// } else {
|
||||
// showOverlayCopilot.value = true
|
||||
// }
|
||||
if (aiCopilotCheck === 'CHECKED') {
|
||||
showOverlayCopilot.value = false
|
||||
} else {
|
||||
showOverlayCopilot.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const aiTipsConfirm = () => {
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
cardInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
name: '',
|
||||
icon: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const emits = defineEmits(['openBlank'])
|
||||
const openBlank = () => {
|
||||
emits('openBlank')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="doc-card" @click="openBlank">
|
||||
<div class="base-show">
|
||||
<Icon><component class="svg-icon item-top-icon" :is="cardInfo.icon"></component></Icon>
|
||||
</div>
|
||||
<div class="base-show show-content">{{ cardInfo.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.doc-card {
|
||||
padding: 8px 0;
|
||||
width: 96px;
|
||||
height: 66px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
&:hover,
|
||||
&:active {
|
||||
background-color: #1f23291a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.show-content {
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.item-top-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
</style>
|
||||
@ -863,7 +863,7 @@ export default {
|
||||
'Please fill in one per line, up to 500 items can be added. Duplicate options and already added options will be automatically filtered out when identifying input',
|
||||
close: 'Close',
|
||||
add: 'Add',
|
||||
sure: 'Confirm',
|
||||
sure: 'Confirm定',
|
||||
uncommitted_tips: 'There are uncommitted permission changes, do you want to submit? ',
|
||||
use: 'Use',
|
||||
check: 'View',
|
||||
@ -1234,8 +1234,8 @@ export default {
|
||||
text_pos_right: 'right',
|
||||
text_pos_top: 'top',
|
||||
text_pos_bottom: 'bottom',
|
||||
text_italic: 'font italic',
|
||||
italic: 'italic',
|
||||
text_italic: 'font tilt',
|
||||
italic: 'tilt',
|
||||
orient: 'direction',
|
||||
horizontal: 'horizontal',
|
||||
vertical: 'vertical',
|
||||
@ -1850,14 +1850,7 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr
|
||||
full_display: 'full display',
|
||||
show_hover_style: 'show mouse hover style',
|
||||
merge_cells: 'merge cells',
|
||||
length_limit: 'length limit',
|
||||
radar_point: 'enable auxiliary points',
|
||||
radar_point_size: 'size',
|
||||
radar_area_color: 'enable area',
|
||||
table_freeze_tip: 'after merging cells, column and row freezing is not supported',
|
||||
merge_cells_tips:
|
||||
'after merging cells, freezing rows and columns and automatic line wrapping will become invalid',
|
||||
merge_cells_break_line_tip: 'after merging cells, automatic line wrapping is not supported'
|
||||
length_limit: 'length limit'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: 'only effective when editing',
|
||||
@ -2272,9 +2265,6 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr
|
||||
day_limit: 'Days cannot be less than 1 and greater than 31'
|
||||
},
|
||||
commons: {
|
||||
language: 'language',
|
||||
help_center: 'Help Center',
|
||||
assistant: 'Assistant',
|
||||
test_connect: 'Test connection',
|
||||
consanguinity: 'blood relationship',
|
||||
collapse_navigation: 'Collapse navigation',
|
||||
@ -2657,36 +2647,6 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr
|
||||
column_name: 'Field name'
|
||||
},
|
||||
visualization: {
|
||||
effective_during_link: 'Public link active',
|
||||
condition_style_set: 'Condition Style Settings',
|
||||
cell_merge_tips:
|
||||
'After merging cells, row/column freezing and automatic line wrapping will be disabled.',
|
||||
image: 'Image',
|
||||
jump_set_tips: 'Drill-down has been set',
|
||||
input_calc_data: 'Enter calculation data',
|
||||
excel_with_format: 'Excel (with format)',
|
||||
show_data: 'View Data',
|
||||
sort: 'Sort',
|
||||
add_query_filter: 'Add Query Condition',
|
||||
edit_query_filter: 'Edit Query Condition',
|
||||
jump_set_tips: 'Redirection has been set',
|
||||
tips_world: 'Tip Words',
|
||||
query_name_space2: 'Spacing between name and selection box',
|
||||
button_color: 'Button Color',
|
||||
button_text: 'Button Text',
|
||||
font_size: 'Font Size',
|
||||
show_button: 'Show Button',
|
||||
query_tips:
|
||||
'If the query button is displayed, the chart query will be triggered only after clicking the button. If not displayed, the query is triggered immediately after selecting the query conditions.',
|
||||
custom_query_bg_color: 'Custom Query Background Color',
|
||||
query_condition_space: 'Query Condition Spacing',
|
||||
query_condition_name: 'Query Condition Name',
|
||||
condition_left: 'Left Side',
|
||||
condition_top: 'Top Side',
|
||||
custom_bg_color: 'Custom Component Background',
|
||||
background_img: 'Background Image',
|
||||
back_parent: 'Back to Parent',
|
||||
ext_fullscreen: 'Exit Fullscreen',
|
||||
no_edit_auth: 'No edit permissions for the target resource, please contact the administrator!',
|
||||
select_target_dashboard_tips: 'Please select the target dashboard',
|
||||
select_target_screen_tips: 'Please select the target data screen',
|
||||
@ -2981,7 +2941,7 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr
|
||||
panel_background: 'Dashboard Background',
|
||||
component_color: 'Component Color',
|
||||
chart_title: 'Chart Title',
|
||||
filter_component: 'Query',
|
||||
filter_component: 'Filter Component',
|
||||
enable_refresh_view: 'Enable Refresh',
|
||||
enable_view_loading: 'Chart Loading Prompt',
|
||||
image_size_tips: 'Please ensure images are no larger than 15MB',
|
||||
|
||||
@ -608,7 +608,6 @@ export default {
|
||||
secret_length: '密鑰長度'
|
||||
},
|
||||
components: {
|
||||
effective_during_link: '公共連結生效',
|
||||
dashboard_style: '儀表板風格',
|
||||
overall_configuration: '整體配置',
|
||||
dashboard_background: '儀表板背景',
|
||||
@ -1811,13 +1810,7 @@ export default {
|
||||
full_display: '全量顯示',
|
||||
show_hover_style: '顯示滑鼠懸浮樣式',
|
||||
merge_cells: '合併儲存格',
|
||||
length_limit: '長度限制',
|
||||
radar_point: '開啟輔助點',
|
||||
radar_point_size: '輔助點大小',
|
||||
radar_area_color: '開啟面積',
|
||||
table_freeze_tip: '合併儲存格後,不支持行列凍結',
|
||||
merge_cells_tips: '合併儲存格後,行列凍結、自動換行會失效',
|
||||
merge_cells_break_line_tip: '合併儲存格後,不支持自動換行'
|
||||
length_limit: '長度限制'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '僅編輯時生效',
|
||||
@ -2221,9 +2214,6 @@ export default {
|
||||
day_limit: '天不能小於1,大於31'
|
||||
},
|
||||
commons: {
|
||||
language: '語言',
|
||||
help_center: '幫助中心',
|
||||
assistant: '小助手',
|
||||
test_connect: '測試連線',
|
||||
consanguinity: '血緣關係',
|
||||
collapse_navigation: '收起導航',
|
||||
@ -2595,34 +2585,6 @@ export default {
|
||||
column_name: '欄位名稱'
|
||||
},
|
||||
visualization: {
|
||||
condition_style_set: '條件樣式設定',
|
||||
cell_merge_tips: '合併單元格後,行列凍結、自動換行將失效。',
|
||||
image: '圖片',
|
||||
jump_set_tips: '已設定下鑽',
|
||||
input_calc_data: '輸入計算數據',
|
||||
excel_with_format: 'Excel(帶格式)',
|
||||
show_data: '查看數據',
|
||||
sort: '排序',
|
||||
add_query_filter: '添加查詢條件',
|
||||
edit_query_filter: '編輯查詢條件',
|
||||
jump_set_tips: '已設定跳轉',
|
||||
tips_world: '提示詞',
|
||||
query_name_space2: '名稱與選框間距',
|
||||
button_color: '按鈕顏色',
|
||||
button_text: '按鈕文字',
|
||||
font_size: '字號',
|
||||
show_button: '展示按鈕',
|
||||
query_tips:
|
||||
'如果展示查詢按鈕,需要點擊該按鈕後才能觸發圖表查詢;如果不展示查詢按鈕,選擇完查詢條件後立即觸發圖表查詢',
|
||||
custom_query_bg_color: '自定義查詢條件背景',
|
||||
query_condition_space: '查詢條件間距',
|
||||
query_condition_name: '查詢條件名稱',
|
||||
condition_left: '左側',
|
||||
condition_top: '上側',
|
||||
custom_bg_color: '自定義組件背景',
|
||||
background_img: '背景圖片',
|
||||
back_parent: '返回上一級',
|
||||
ext_fullscreen: '退出全屏',
|
||||
no_edit_auth: '目標資源沒有編輯權限,請聯繫管理員!',
|
||||
select_target_dashboard_tips: '請選擇目標儀表板',
|
||||
select_target_screen_tips: '請選擇目標數據大屏',
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
export default {
|
||||
common: {
|
||||
timeout_tips: '请求超时,请稍后再试',
|
||||
component: {
|
||||
input: '单行输入',
|
||||
textarea: '多行输入',
|
||||
@ -1813,13 +1812,7 @@ export default {
|
||||
full_display: '全量显示',
|
||||
show_hover_style: '显示鼠标悬浮样式',
|
||||
merge_cells: '合并单元格',
|
||||
length_limit: '长度限制',
|
||||
radar_point: '开启辅助点',
|
||||
radar_point_size: '辅助点大小',
|
||||
radar_area_color: '开启面积',
|
||||
table_freeze_tip: '合并单元格后,不支持行列冻结',
|
||||
merge_cells_tips: '合并单元格后,行列冻结、自动换行会失效',
|
||||
merge_cells_break_line_tip: '合并单元格后,不支持自动换行'
|
||||
length_limit: '长度限制'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '仅编辑时生效',
|
||||
@ -2223,9 +2216,6 @@ export default {
|
||||
day_limit: '天不能小于1,大于31'
|
||||
},
|
||||
commons: {
|
||||
language: '语言',
|
||||
help_center: '帮助中心',
|
||||
assistant: '小助手',
|
||||
test_connect: '测试连接',
|
||||
consanguinity: '血缘关系',
|
||||
collapse_navigation: '收起导航',
|
||||
@ -2597,35 +2587,6 @@ export default {
|
||||
column_name: '字段名称'
|
||||
},
|
||||
visualization: {
|
||||
effective_during_link: '公共链接生效',
|
||||
condition_style_set: '条件样式设置',
|
||||
cell_merge_tips: '合并单元格后,行列冻结、自动换行会失效。',
|
||||
image: '图片',
|
||||
jump_set_tips: '已设置下钻',
|
||||
input_calc_data: '输入计算数据',
|
||||
excel_with_format: 'Excel(带格式)',
|
||||
show_data: '查看数据',
|
||||
sort: '排序',
|
||||
add_query_filter: '添加查询条件',
|
||||
edit_query_filter: '编辑查询条件',
|
||||
jump_set_tips: '已设置跳转',
|
||||
tips_world: '提示词',
|
||||
query_name_space2: '名称与选框间距',
|
||||
button_color: '按钮颜色',
|
||||
button_text: '按钮文字',
|
||||
font_size: '字号',
|
||||
show_button: '展示按钮',
|
||||
query_tips:
|
||||
'如果展示查询按钮,需要点击该按钮后才能触发图表查询;如果不展示查询按钮,选择完查询条件后立即触发图表查询',
|
||||
custom_query_bg_color: '自定义查询条件背景',
|
||||
query_condition_space: '查询条件间距',
|
||||
query_condition_name: '查询条件名称',
|
||||
condition_left: '左侧',
|
||||
condition_top: '上侧',
|
||||
custom_bg_color: '自定义组件背景',
|
||||
background_img: '背景图片',
|
||||
back_parent: '返回上一级',
|
||||
ext_fullscreen: '退出全屏',
|
||||
no_edit_auth: '目标资源没有编辑权限,请联系管理员!',
|
||||
select_target_dashboard_tips: '请选择目标仪表板',
|
||||
select_target_screen_tips: '请选择目标数据大屏',
|
||||
|
||||
@ -334,18 +334,6 @@ declare interface ChartBasicStyle {
|
||||
* 最大行数
|
||||
*/
|
||||
maxLines?: number
|
||||
/**
|
||||
* 雷达图辅助点
|
||||
*/
|
||||
radarShowPoint: boolean
|
||||
/**
|
||||
* 雷达图辅助点大小
|
||||
*/
|
||||
radarPointSize: number
|
||||
/**
|
||||
* 雷达图面积颜色开关
|
||||
*/
|
||||
radarAreaColor: boolean
|
||||
}
|
||||
/**
|
||||
* 表头属性
|
||||
|
||||
@ -474,7 +474,7 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
const newView = {
|
||||
...JSON.parse(JSON.stringify(BASE_VIEW_CONFIG)),
|
||||
id: component.id,
|
||||
title: t('visualization.query_component'),
|
||||
title: '查询组件',
|
||||
type: component.innerType,
|
||||
customStyle: {
|
||||
component: {
|
||||
|
||||
@ -24,11 +24,6 @@ export const useRequestStore = defineStore('request', {
|
||||
setLoadingMap(value: object) {
|
||||
this.loadingMap = value
|
||||
},
|
||||
resetLoadingMap() {
|
||||
for (const key in this.loadingMap) {
|
||||
this.loadingMap[key] = 0
|
||||
}
|
||||
},
|
||||
addLoading(key: string) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.loadingMap, key)) {
|
||||
const map = this.loadingMap
|
||||
|
||||
@ -187,16 +187,16 @@ function move(keyCode) {
|
||||
const scale = dvMainStore.canvasStyleData.scale / 100
|
||||
if (keyCode === leftKey) {
|
||||
curComponent.value.style.left = curComponent.value.style.left - scale
|
||||
groupAreaAdaptor(-scale, 0)
|
||||
groupAreaAdaptor(-1, 0)
|
||||
} else if (keyCode === rightKey) {
|
||||
curComponent.value.style.left = curComponent.value.style.left + scale
|
||||
groupAreaAdaptor(scale, 0)
|
||||
groupAreaAdaptor(1, 0)
|
||||
} else if (keyCode === upKey) {
|
||||
curComponent.value.style.top = curComponent.value.style.top - scale
|
||||
groupAreaAdaptor(0, -scale)
|
||||
groupAreaAdaptor(0, -1)
|
||||
} else if (keyCode === downKey) {
|
||||
curComponent.value.style.top = curComponent.value.style.top + scale
|
||||
groupAreaAdaptor(0, scale)
|
||||
groupAreaAdaptor(0, 1)
|
||||
}
|
||||
snapshotStore.recordSnapshotCache('key-move')
|
||||
}
|
||||
@ -212,11 +212,6 @@ function groupAreaAdaptor(leftOffset = 0, topOffset = 0) {
|
||||
width: parentNode.offsetWidth,
|
||||
height: parentNode.offsetHeight
|
||||
})
|
||||
} else if (curComponent.value.component === 'GroupArea' && areaData.value.components.length > 0) {
|
||||
areaData.value.components.forEach(component => {
|
||||
component.style.top = component.style.top + topOffset
|
||||
component.style.left = component.style.left + leftOffset
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import { cos, sin } from '@/utils/translate'
|
||||
import {
|
||||
CHART_FONT_FAMILY_MAP,
|
||||
CHART_FONT_FAMILY_MAP_TRANS,
|
||||
DEFAULT_COLOR_CASE,
|
||||
DEFAULT_COLOR_CASE_DARK,
|
||||
DEFAULT_INDICATOR_STYLE
|
||||
DEFAULT_COLOR_CASE_DARK
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { defaultTo, merge } from 'lodash-es'
|
||||
import { merge } from 'lodash-es'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
|
||||
export const LIGHT_THEME_COLOR_MAIN = '#000000'
|
||||
@ -116,7 +113,7 @@ export function colorRgb(color, opacity) {
|
||||
}
|
||||
|
||||
export const customAttrTrans = {
|
||||
basicStyle: ['barWidth', 'lineWidth', 'lineSymbolSize', 'tableColumnWidth'],
|
||||
basicStyle: ['barWidth', 'lineWidth', 'lineSymbolSize'],
|
||||
tableHeader: ['tableTitleFontSize', 'tableTitleHeight'],
|
||||
tableCell: ['tableItemFontSize', 'tableItemHeight'],
|
||||
misc: [
|
||||
@ -427,10 +424,7 @@ export function adaptCurTheme(customStyle, customAttr) {
|
||||
|
||||
export function adaptTitleFontFamily(fontFamily, viewInfo) {
|
||||
if (viewInfo) {
|
||||
viewInfo.customStyle['text']['fontFamily'] = defaultTo(
|
||||
CHART_FONT_FAMILY_MAP_TRANS[fontFamily],
|
||||
fontFamily
|
||||
)
|
||||
viewInfo.customStyle['text']['fontFamily'] = fontFamily
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
<script lang="ts" setup>
|
||||
import logo from '@/assets/svg/logo.svg'
|
||||
import aboutBg from '@/assets/img/about-bg.png'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted, h } from 'vue'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { F2CLicense } from './index'
|
||||
import { validateApi, buildVersionApi, updateInfoApi } from '@/api/about'
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
import {
|
||||
validateApi,
|
||||
buildVersionApi,
|
||||
updateInfoApi,
|
||||
checkFreeApi,
|
||||
syncFreeApi,
|
||||
delFreeApi
|
||||
} from '@/api/about'
|
||||
import { ElMessage, ElMessageBox, Action } from 'element-plus-secondary'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
@ -122,11 +129,65 @@ const update = (licKey: string) => {
|
||||
ElMessage.success(t('about.update_success'))
|
||||
const info = getLicense(response.data)
|
||||
setLicense(info)
|
||||
checkFree()
|
||||
} else {
|
||||
ElMessage.warning(response.data.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const autoSync = ref(true)
|
||||
const checkFree = () => {
|
||||
checkFreeApi().then(res => {
|
||||
if (res.data) {
|
||||
if (autoSync.value) {
|
||||
syncFree()
|
||||
return
|
||||
}
|
||||
// do something
|
||||
const title = '存在未同步的资源数据,请谨慎操作!'
|
||||
const childrenDomList = [h('strong', null, title)]
|
||||
ElMessageBox.confirm('', {
|
||||
confirmButtonType: 'primary',
|
||||
type: 'warning',
|
||||
autofocus: false,
|
||||
dangerouslyUseHTMLString: true,
|
||||
message: h('div', { class: 'free-sync-tip-box' }, childrenDomList),
|
||||
showClose: false,
|
||||
cancelButtonText: '删除',
|
||||
cancelButtonClass: 'free-cancel-bt',
|
||||
showCancelButton: false,
|
||||
preButtonType: 'danger',
|
||||
preButtonText: '删除',
|
||||
showPreButton: true,
|
||||
confirmButtonText: '同步',
|
||||
callback: (action: Action) => {
|
||||
if (action === 'confirm') {
|
||||
syncFree()
|
||||
} else {
|
||||
delFree
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const delFree = () => {
|
||||
delFreeApi().then(res => {
|
||||
if (!res.code && !res.msg) {
|
||||
ElMessage.success(t('common.delete_success'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const syncFree = () => {
|
||||
syncFreeApi().then(res => {
|
||||
if (!res.code && !res.msg) {
|
||||
ElMessage.success('同步成功')
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@ -3,7 +3,6 @@ import { computed, nextTick, onMounted, PropType, reactive, ref, watch } from 'v
|
||||
import { getGeoJsonFile, parseJson } from '../../../js/util'
|
||||
import { forEach, debounce } from 'lodash-es'
|
||||
import { toRefs } from 'vue'
|
||||
import { getCustomGeoArea } from '@/api/map'
|
||||
|
||||
const props = defineProps({
|
||||
chart: {
|
||||
@ -71,11 +70,7 @@ const getAreaMapping = async areaId => {
|
||||
return {}
|
||||
}
|
||||
if (areaId.startsWith('custom_')) {
|
||||
const areaList = (await getCustomGeoArea(areaId)).data
|
||||
return areaList.reduce((p, n) => {
|
||||
p[n.name] = n.name
|
||||
return p
|
||||
}, {})
|
||||
areaId = '156'
|
||||
}
|
||||
const geoJson = await getGeoJsonFile(areaId)
|
||||
return geoJson.features.reduce((p, n) => {
|
||||
|
||||
@ -496,9 +496,7 @@ init()
|
||||
<el-col v-if="props.chart.type && props.chart.type === 'indicator'">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">{{
|
||||
$t('visualization.condition_style_set')
|
||||
}}</span>
|
||||
<span class="label" :class="'label-' + props.themes">条件样式设置</span>
|
||||
<span class="right-btns">
|
||||
<span
|
||||
class="set-text-info"
|
||||
@ -596,9 +594,7 @@ init()
|
||||
<el-col v-show="showProperty('tableThreshold')">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">{{
|
||||
$t('visualization.condition_style_set')
|
||||
}}</span>
|
||||
<span class="label" :class="'label-' + props.themes">条件样式设置</span>
|
||||
<span class="right-btns">
|
||||
<span
|
||||
class="set-text-info"
|
||||
@ -796,16 +792,14 @@ init()
|
||||
<el-col v-show="showProperty('lineThreshold')">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">{{
|
||||
$t('visualization.condition_style_set')
|
||||
}}</span>
|
||||
<span class="label" :class="'label-' + props.themes">条件样式设置</span>
|
||||
<span class="right-btns">
|
||||
<span
|
||||
class="set-text-info"
|
||||
:class="{ 'set-text-info-dark': themes === 'dark' }"
|
||||
v-if="state.thresholdForm?.tableThreshold?.length > 0"
|
||||
>
|
||||
$t('visualization.already_setting')
|
||||
已设置
|
||||
</span>
|
||||
<el-button
|
||||
:title="t('chart.edit')"
|
||||
|
||||
@ -283,7 +283,7 @@ initParams()
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="t('components.title_color')"
|
||||
label="标题颜色"
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
@ -330,7 +330,7 @@ initParams()
|
||||
size="small"
|
||||
v-model="commonBackgroundPop.backgroundColorSelect"
|
||||
>
|
||||
{{ t('visualization.custom_bg_color') }}
|
||||
自定义组件背景
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-row style="padding-left: 20px" :gutter="8">
|
||||
@ -389,14 +389,10 @@ initParams()
|
||||
label="innerImage"
|
||||
:effect="themes"
|
||||
>
|
||||
{{ t('visualization.background_color') }}
|
||||
</el-radio>
|
||||
<el-radio key="color" v-else label="color" :effect="themes">
|
||||
{{ t('visualization.background_color') }}
|
||||
</el-radio>
|
||||
<el-radio label="outerImage" :effect="themes">
|
||||
{{ t('visualization.background_img') }}
|
||||
背景颜色
|
||||
</el-radio>
|
||||
<el-radio key="color" v-else label="color" :effect="themes"> 背景颜色 </el-radio>
|
||||
<el-radio label="outerImage" :effect="themes"> 背景图片 </el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@ -434,7 +430,7 @@ initParams()
|
||||
class="image-hint"
|
||||
:class="`image-hint_${themes}`"
|
||||
>
|
||||
{{ t('visualization.pic_import_tips') }}
|
||||
支持JPG、PNG、GIF、SVG
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
@ -469,7 +465,7 @@ initParams()
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :effect="themes" name="addition" :title="t('v_query.query_condition')">
|
||||
<el-collapse-item :effect="themes" name="addition" title="查询条件">
|
||||
<el-form @keydown.stop.prevent.enter label-position="top">
|
||||
<el-form-item class="form-item margin-bottom-8" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
@ -505,7 +501,7 @@ initParams()
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="t('visualization.text_html')"
|
||||
label="文本"
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
@ -548,7 +544,7 @@ initParams()
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="t('visualization.tips_world')"
|
||||
label="提示词"
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
@ -580,7 +576,7 @@ initParams()
|
||||
size="small"
|
||||
v-model="chart.customStyle.component.bgColorShow"
|
||||
>
|
||||
{{ t('visualization.custom_query_bg_color') }}
|
||||
自定义查询条件背景
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@ -600,7 +596,7 @@ initParams()
|
||||
<el-form-item
|
||||
:effect="themes"
|
||||
class="form-item"
|
||||
:label="t('visualization.query_condition_space')"
|
||||
label="查询条件间距"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-input-number
|
||||
@ -616,7 +612,7 @@ initParams()
|
||||
:themes="themes"
|
||||
v-model="chart.customStyle.component.labelShow"
|
||||
name="legend"
|
||||
:title="t('visualization.query_condition_name')"
|
||||
title="查询条件名称"
|
||||
>
|
||||
<el-form
|
||||
:class="!chart.customStyle.component.labelShow && 'is-disabled'"
|
||||
@ -630,12 +626,8 @@ initParams()
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-radio-group :effect="themes" v-model="chart.customStyle.component.layout">
|
||||
<el-radio label="vertical" :effect="themes">
|
||||
{{ t('visualization.condition_top') }}
|
||||
</el-radio>
|
||||
<el-radio label="horizontal" :effect="themes">
|
||||
{{ t('visualization.condition_left') }}
|
||||
</el-radio>
|
||||
<el-radio label="vertical" :effect="themes"> 上侧 </el-radio>
|
||||
<el-radio label="horizontal" :effect="themes"> 左侧 </el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@ -648,11 +640,7 @@ initParams()
|
||||
is-custom
|
||||
v-model="chart.customStyle.component.labelColor"
|
||||
:predefine="predefineColors"
|
||||
/><el-tooltip
|
||||
:content="t('visualization.font_size')"
|
||||
:effect="toolTip"
|
||||
placement="top"
|
||||
>
|
||||
/><el-tooltip content="字号" :effect="toolTip" placement="top">
|
||||
<el-select
|
||||
style="width: 80px; margin: 0 8px"
|
||||
:effect="themes"
|
||||
@ -710,7 +698,7 @@ initParams()
|
||||
<el-form-item
|
||||
:effect="themes"
|
||||
class="form-item"
|
||||
:label="t('visualization.query_name_space2')"
|
||||
label="名称与选框间距"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-input-number
|
||||
@ -728,7 +716,7 @@ initParams()
|
||||
<el-form-item
|
||||
:effect="themes"
|
||||
class="form-item"
|
||||
:label="t('visualization.show_button')"
|
||||
label="展示按钮"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-checkbox-group :effect="themes" v-model="chart.customStyle.component.btnList">
|
||||
@ -736,7 +724,7 @@ initParams()
|
||||
{{ t('commons.adv_search.search') }}
|
||||
<el-tooltip
|
||||
:effect="toolTip"
|
||||
:content="t('visualization.query_tips')"
|
||||
content="如果展示查询按钮,需要点击该按钮后才能触发图表查询;如果不展示查询按钮,选择完查询条件后立即触发图表查询"
|
||||
placement="top"
|
||||
>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
@ -753,11 +741,7 @@ initParams()
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:label="t('visualization.button_color')"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-form-item class="form-item" label="按钮颜色" :class="'form-item-' + themes">
|
||||
<el-color-picker
|
||||
:effect="themes"
|
||||
:trigger-width="108"
|
||||
@ -767,7 +751,7 @@ initParams()
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="t('visualization.button_text')"
|
||||
label="按钮文字"
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
@ -776,11 +760,7 @@ initParams()
|
||||
is-custom
|
||||
v-model="chart.customStyle.component.labelColorBtn"
|
||||
:predefine="predefineColors"
|
||||
/><el-tooltip
|
||||
:content="t('visualization.font_size')"
|
||||
:effect="toolTip"
|
||||
placement="top"
|
||||
>
|
||||
/><el-tooltip content="字号" :effect="toolTip" placement="top">
|
||||
<el-select
|
||||
style="width: 80px; margin: 0 8px"
|
||||
:effect="themes"
|
||||
|
||||
@ -320,17 +320,6 @@ const mapCustomRangeValidate = prop => {
|
||||
}
|
||||
changeBasicStyle(prop)
|
||||
}
|
||||
/**
|
||||
* 表格是否合并单元格
|
||||
*/
|
||||
const mergeCell = computed(() => {
|
||||
if (COLUMN_WIDTH_TYPE.includes(props.chart.type)) {
|
||||
let { customAttr } = JSON.parse(JSON.stringify(props.chart))
|
||||
const { tableCell } = customAttr
|
||||
return tableCell.mergeCells
|
||||
}
|
||||
return false
|
||||
})
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
@ -1068,21 +1057,12 @@ onMounted(() => {
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
:disabled="mergeCell"
|
||||
v-model="state.basicStyleForm.autoWrap"
|
||||
@change="changeBasicStyle('autoWrap')"
|
||||
>
|
||||
<span class="data-area-label">
|
||||
<span style="margin-right: 4px">{{ t('chart.table_auto_break_line') }}</span>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom" v-if="mergeCell">
|
||||
<template #content>
|
||||
<div>{{ t('chart.merge_cells_break_line_tip') }}</div>
|
||||
</template>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom" v-else>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
<div>{{ t('chart.table_break_line_tip') }}</div>
|
||||
</template>
|
||||
@ -1106,7 +1086,6 @@ onMounted(() => {
|
||||
:show-input-controls="false"
|
||||
:min="1"
|
||||
:step="1"
|
||||
:disabled="mergeCell"
|
||||
@change="changeBasicStyle('maxLines')"
|
||||
/>
|
||||
</el-form-item>
|
||||
@ -1299,53 +1278,6 @@ onMounted(() => {
|
||||
<el-radio :effect="themes" label="circle">{{ t('chart.circle') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('radarShowPoint')"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.radarShowPoint"
|
||||
@change="changeBasicStyle('radarShowPoint')"
|
||||
>
|
||||
{{ $t('chart.radar_point') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
style="padding-left: 20px"
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.radar_point_size')"
|
||||
v-if="showProperty('radarPointSize')"
|
||||
>
|
||||
<el-input-number
|
||||
style="width: 100%"
|
||||
:effect="themes"
|
||||
controls-position="right"
|
||||
size="middle"
|
||||
:min="0"
|
||||
:max="30"
|
||||
:disabled="!state.basicStyleForm.radarShowPoint"
|
||||
v-model="state.basicStyleForm.radarPointSize"
|
||||
@change="changeBasicStyle('radarPointSize')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('radarAreaColor')"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.radarAreaColor"
|
||||
@change="changeBasicStyle('radarAreaColor')"
|
||||
>
|
||||
{{ $t('chart.radar_area_color') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<!--radar end-->
|
||||
<!--scatter start-->
|
||||
<el-form-item
|
||||
|
||||
@ -282,7 +282,8 @@ onMounted(() => {
|
||||
|
||||
:deep(.ed-tabs__content) {
|
||||
height: calc(100% - 35px);
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
.padding-tab {
|
||||
|
||||
@ -473,9 +473,6 @@ const noFullDisplay = computed(() => {
|
||||
const isGauge = computed(() => {
|
||||
return props.chart.type === 'gauge'
|
||||
})
|
||||
const isProgressBar = computed(() => {
|
||||
return props.chart.type === 'progress-bar'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -943,7 +940,7 @@ const isProgressBar = computed(() => {
|
||||
<el-checkbox
|
||||
v-model="state.labelForm.showQuota"
|
||||
:effect="themes"
|
||||
:disabled="isProgressBar ? false : checkLabelContent('showQuota')"
|
||||
:disabled="checkLabelContent('showQuota')"
|
||||
size="small"
|
||||
label="quota"
|
||||
@change="changeLabelAttr('showQuota')"
|
||||
@ -1063,12 +1060,12 @@ const isProgressBar = computed(() => {
|
||||
<el-checkbox
|
||||
v-model="state.labelForm.showProportion"
|
||||
:effect="themes"
|
||||
:disabled="isProgressBar ? false : checkLabelContent('showProportion')"
|
||||
:disabled="checkLabelContent('showProportion')"
|
||||
size="small"
|
||||
label="proportion"
|
||||
@change="changeLabelAttr('showProportion')"
|
||||
>
|
||||
{{ isProgressBar ? t('chart.value_formatter_percent') : t('chart.proportion') }}
|
||||
{{ t('chart.proportion') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<div style="padding-left: 22px">
|
||||
|
||||
@ -332,22 +332,7 @@ onMounted(() => {
|
||||
v-model="state.tableCellForm.tableFreeze"
|
||||
@change="changeTableCell('tableFreeze')"
|
||||
>
|
||||
<span class="data-area-label">
|
||||
<span style="margin-right: 4px">{{ t('chart.table_freeze') }}</span>
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
placement="bottom"
|
||||
v-if="state.tableCellForm.mergeCells"
|
||||
>
|
||||
<template #content>
|
||||
<div>{{ t('chart.table_freeze_tip') }}</div>
|
||||
</template>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
{{ t('chart.table_freeze') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-row :gutter="8" v-if="showProperty('tableFreeze')">
|
||||
@ -409,7 +394,7 @@ onMounted(() => {
|
||||
<span style="margin-right: 4px">{{ t('chart.merge_cells') }}</span>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
<div>{{ t('chart.merge_cells_tips') }}</div>
|
||||
<div>合并单元格后,行列冻结、自动换行会失效。</div>
|
||||
</template>
|
||||
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
|
||||
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>
|
||||
|
||||
@ -84,7 +84,7 @@ defineExpose({
|
||||
<el-dialog
|
||||
width="896px"
|
||||
append-to-body
|
||||
:title="$t('chart.add_filter')"
|
||||
title="添加过滤"
|
||||
destroy-on-close
|
||||
class="de-dialog-form filter-tree-cont"
|
||||
v-model="dialogVisible"
|
||||
|
||||
@ -1102,19 +1102,13 @@ const onFunctionCfgChange = val => {
|
||||
}
|
||||
|
||||
const onBackgroundChange = val => {
|
||||
// 修复#13299
|
||||
if (curComponent.value.id === view.value?.id) {
|
||||
curComponent.value.commonBackground = val
|
||||
if (mobileInPc.value) {
|
||||
//移动端设计
|
||||
useEmitt().emitter.emit('onMobileStatusChange', {
|
||||
type: 'componentStyleChange',
|
||||
value: {
|
||||
type: 'commonBackground',
|
||||
component: JSON.parse(JSON.stringify(curComponent.value))
|
||||
}
|
||||
})
|
||||
}
|
||||
curComponent.value.commonBackground = val
|
||||
if (mobileInPc.value) {
|
||||
//移动端设计
|
||||
useEmitt().emitter.emit('onMobileStatusChange', {
|
||||
type: 'componentStyleChange',
|
||||
value: { type: 'commonBackground', component: JSON.parse(JSON.stringify(curComponent.value)) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -3280,11 +3274,7 @@ const deleteChartFieldItem = id => {
|
||||
@add-ds-window="addDsWindow"
|
||||
@on-dataset-change="recordSnapshotInfo('calcData')"
|
||||
/>
|
||||
<el-tooltip
|
||||
:effect="toolTip"
|
||||
:content="$t('deDataset.edit_dataset')"
|
||||
placement="top"
|
||||
>
|
||||
<el-tooltip :effect="toolTip" content="编辑数据集" placement="top">
|
||||
<el-icon
|
||||
v-if="curDatasetWeight >= 7 && !isDataEaseBi"
|
||||
class="field-search-icon-btn"
|
||||
|
||||
@ -1112,20 +1112,6 @@ export const BASE_ECHARTS_SELECT = {
|
||||
}
|
||||
}
|
||||
|
||||
export const CHART_FONT_FAMILY_ORIGIN = [
|
||||
{ name: '微软雅黑', value: 'Microsoft YaHei' },
|
||||
{ name: '宋体', value: 'SimSun, "Songti SC", STSong' },
|
||||
{ name: '黑体', value: 'SimHei, Helvetica' },
|
||||
{ name: '楷体', value: 'KaiTi, "Kaiti SC", STKaiti' }
|
||||
]
|
||||
|
||||
export const CHART_FONT_FAMILY_MAP_TRANS = {
|
||||
'Microsoft YaHei': 'Microsoft YaHei',
|
||||
'SimSun, "Songti SC", STSong': 'SimSun',
|
||||
'SimHei, Helvetica': 'SimHei',
|
||||
'KaiTi, "Kaiti SC", STKaiti': 'KaiTi'
|
||||
}
|
||||
|
||||
export const CHART_FONT_FAMILY = [
|
||||
{ name: '微软雅黑', value: 'Microsoft YaHei' },
|
||||
{ name: '宋体', value: 'SimSun' },
|
||||
@ -1560,7 +1546,7 @@ export const CHART_TYPE_CONFIGS = [
|
||||
export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
alpha: 100,
|
||||
tableBorderColor: '#CCCCCC',
|
||||
tableScrollBarColor: '#1f23294d',
|
||||
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
|
||||
tableColumnMode: 'adapt',
|
||||
tableColumnWidth: 100,
|
||||
tableFieldWidth: [],
|
||||
@ -1633,10 +1619,7 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
customIcon: '',
|
||||
showHoverStyle: true,
|
||||
autoWrap: false,
|
||||
maxLines: 3,
|
||||
radarShowPoint: true,
|
||||
radarPointSize: 4,
|
||||
radarAreaColor: true
|
||||
maxLines: 3
|
||||
}
|
||||
|
||||
export const BASE_VIEW_CONFIG = {
|
||||
|
||||
@ -55,7 +55,7 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
'background-overall-component': ['all'],
|
||||
'border-style': ['all'],
|
||||
'basic-style-selector': ['colors', 'alpha', 'gradient', 'radiusColumnBar'],
|
||||
'label-selector': ['hPosition', 'color', 'fontSize', 'showQuota', 'showProportion'],
|
||||
'label-selector': ['hPosition', 'color', 'fontSize'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'tooltipFormatter', 'show'],
|
||||
'y-axis-selector': [
|
||||
'name',
|
||||
@ -249,30 +249,27 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
|
||||
protected configLabel(chart: Chart, options: BarOptions): BarOptions {
|
||||
const baseOptions = super.configLabel(chart, options)
|
||||
if (!baseOptions.label) return baseOptions
|
||||
if (!baseOptions.label.layout?.[0]) {
|
||||
baseOptions.label.layout = [{ type: 'limit-in-canvas' }]
|
||||
if (!baseOptions.label) {
|
||||
return baseOptions
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
content: item => {
|
||||
if (item.type === 'target') return ''
|
||||
let text = ''
|
||||
if (labelAttr.showQuota) text += valueFormatter(item.value, labelAttr.quotaLabelFormatter)
|
||||
if (labelAttr.showProportion) {
|
||||
let proportion = item.originalProgress.toFixed(labelAttr.reserveDecimalCount) + '%'
|
||||
if (labelAttr.showQuota) {
|
||||
proportion = ` (${proportion}) `
|
||||
}
|
||||
text += proportion
|
||||
if (item.type === 'target') {
|
||||
return ''
|
||||
}
|
||||
return text
|
||||
return item.originalProgress.toFixed(2) + '%'
|
||||
}
|
||||
}
|
||||
if (label.position === 'top') label.position = 'right'
|
||||
return { ...baseOptions, label }
|
||||
if (label.position === 'top') {
|
||||
label.position = 'right'
|
||||
}
|
||||
return {
|
||||
...baseOptions,
|
||||
label
|
||||
}
|
||||
}
|
||||
protected configYAxis(chart: Chart, options: BarOptions): BarOptions {
|
||||
const baseOption = super.configYAxis(chart, options)
|
||||
@ -303,8 +300,6 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
chart.customStyle.legend.show = false
|
||||
chart.customAttr.label.show = true
|
||||
chart.customAttr.label.position = 'right'
|
||||
chart.customAttr.label.showQuota = false
|
||||
chart.customAttr.label.showProportion = true
|
||||
return chart
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
MapMouseEvent
|
||||
} from '@/views/chart/components/js/panel/charts/map/common'
|
||||
import { flow, getGeoJsonFile, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
|
||||
import { cloneDeep, isEmpty } from 'lodash-es'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { FeatureCollection } from '@antv/l7plot/dist/esm/plots/choropleth/types'
|
||||
import {
|
||||
handleGeoJson,
|
||||
@ -22,9 +22,6 @@ import {
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
import { configCarouselTooltip } from '@/views/chart/components/js/panel/charts/map/tooltip-carousel'
|
||||
import { getCustomGeoArea } from '@/api/map'
|
||||
import { TextLayer } from '@antv/l7plot/dist/esm'
|
||||
import { centroid } from '@turf/centroid'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -56,23 +53,12 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
}
|
||||
|
||||
async drawChart(drawOption: L7PlotDrawOptions<Choropleth>): Promise<Choropleth> {
|
||||
const { chart, level, areaId, container, action, scope } = drawOption
|
||||
const { chart, level, areaId, container, action } = drawOption
|
||||
if (!areaId) {
|
||||
return
|
||||
}
|
||||
chart.container = container
|
||||
let geoJson = {} as FeatureCollection
|
||||
let customSubArea: CustomGeoSubArea[] = []
|
||||
if (areaId.startsWith('custom_') || scope) {
|
||||
customSubArea = (await getCustomGeoArea(areaId)).data || []
|
||||
customSubArea.forEach(a => (a.scopeArr = a.scope?.split(',') || []))
|
||||
geoJson = cloneDeep(await getGeoJsonFile('156'))
|
||||
if (scope) {
|
||||
geoJson.features = geoJson.features.filter(f => scope.includes('156' + f.properties.adcode))
|
||||
}
|
||||
} else {
|
||||
geoJson = cloneDeep(await getGeoJsonFile(areaId))
|
||||
}
|
||||
const geoJson = cloneDeep(await getGeoJsonFile(areaId))
|
||||
let options: ChoroplethOptions = {
|
||||
preserveDrawingBuffer: true,
|
||||
map: {
|
||||
@ -115,27 +101,19 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
// 禁用线上地图数据
|
||||
customFetchGeoData: () => null
|
||||
}
|
||||
const context: Record<string, any> = { drawOption, geoJson, customSubArea }
|
||||
const context = { drawOption, geoJson }
|
||||
options = this.setupOptions(chart, options, context)
|
||||
|
||||
const tooltip = deepCopy(options.tooltip)
|
||||
options = { ...options, tooltip: { ...tooltip, showComponent: false } }
|
||||
const view = new Choropleth(container, options)
|
||||
const dotLayer = this.getDotLayer(chart, geoJson, drawOption, customSubArea)
|
||||
if (!areaId.startsWith('custom_')) {
|
||||
dotLayer.options = { ...dotLayer.options, tooltip }
|
||||
}
|
||||
const dotLayer = this.getDotLayer(chart, geoJson, drawOption)
|
||||
dotLayer.options = { ...dotLayer.options, tooltip }
|
||||
this.configZoomButton(chart, view)
|
||||
mapRendering(container)
|
||||
view.once('loaded', () => {
|
||||
// 修改地图鼠标样式为默认
|
||||
view.scene.map._canvasContainer.lastElementChild.style.cursor = 'default'
|
||||
const { layers } = context
|
||||
if (layers) {
|
||||
layers.forEach(l => {
|
||||
view.addLayer(l)
|
||||
})
|
||||
}
|
||||
dotLayer.addToScene(view.scene)
|
||||
dotLayer.once('add', () => {
|
||||
mapRendered(container)
|
||||
@ -143,22 +121,15 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
view.scene.map['keyboard'].disable()
|
||||
dotLayer.on('dotLayer:click', (ev: MapMouseEvent) => {
|
||||
const data = ev.feature.properties
|
||||
let adcode, scope
|
||||
if (areaId.startsWith('custom_')) {
|
||||
adcode = '156'
|
||||
const area = customSubArea.find(a => a.name === data.name)
|
||||
scope = area?.scopeArr
|
||||
} else {
|
||||
adcode = view.currentDistrictData.features.find(
|
||||
i => i.properties.name === ev.feature.properties.name
|
||||
)?.properties.adcode
|
||||
}
|
||||
const adcode = view.currentDistrictData.features.find(
|
||||
i => i.properties.name === ev.feature.properties.name
|
||||
)?.properties.adcode
|
||||
action({
|
||||
x: ev.x,
|
||||
y: ev.y,
|
||||
data: {
|
||||
data,
|
||||
extra: { adcode, scope }
|
||||
extra: { adcode: adcode }
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -173,14 +144,28 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
private getDotLayer(
|
||||
chart: Chart,
|
||||
geoJson: FeatureCollection,
|
||||
drawOption: L7PlotDrawOptions<Choropleth>,
|
||||
customSubArea: CustomGeoSubArea[]
|
||||
drawOption: L7PlotDrawOptions<Choropleth>
|
||||
): IPlotLayer {
|
||||
const { areaId } = drawOption
|
||||
const { basicStyle, tooltip } = parseJson(chart.customAttr)
|
||||
const areaMap = chart.data?.data?.reduce((obj, value) => {
|
||||
obj[value['field']] = { value: value.value, data: value }
|
||||
return obj
|
||||
}, {})
|
||||
const dotData = []
|
||||
geoJson.features.forEach(item => {
|
||||
const name = item.properties['name']
|
||||
if (areaMap?.[name]?.value) {
|
||||
dotData.push({
|
||||
x: item.properties['centroid'][0],
|
||||
y: item.properties['centroid'][1],
|
||||
size: areaMap[name].value,
|
||||
properties: areaMap[name].data,
|
||||
name: name
|
||||
})
|
||||
}
|
||||
})
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
const { bubbleCfg } = parseJson(chart.senior)
|
||||
const { offsetHeight, offsetWidth } = document.getElementById(drawOption.container)
|
||||
const dotData = []
|
||||
const options: DotOptions = {
|
||||
source: {
|
||||
data: dotData,
|
||||
@ -205,120 +190,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
state: {
|
||||
active: { color: 'rgba(30,90,255,1)' }
|
||||
},
|
||||
tooltip: {
|
||||
showComponent: tooltip.show
|
||||
}
|
||||
}
|
||||
if (areaId.startsWith('custom_')) {
|
||||
const geoJsonMap = geoJson.features.reduce((p, n) => {
|
||||
if (n.properties['adcode']) {
|
||||
p['156' + n.properties['adcode']] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
const { areaMapping } = parseJson(chart.senior)
|
||||
const customAreaMap = customSubArea.reduce((p, n) => {
|
||||
const mappedName = areaMapping?.[areaId]?.[n.name]
|
||||
if (mappedName) {
|
||||
n.name = mappedName
|
||||
}
|
||||
p[n.name] = n
|
||||
return p
|
||||
}, {})
|
||||
chart.data?.data?.forEach(d => {
|
||||
const area = customAreaMap[d.name]
|
||||
if (area) {
|
||||
const areaJsonArr = []
|
||||
area.scopeArr?.forEach(adcode => {
|
||||
const json = geoJsonMap[adcode]
|
||||
json && areaJsonArr.push(json)
|
||||
})
|
||||
if (areaJsonArr.length) {
|
||||
const areaJson: FeatureCollection = {
|
||||
type: 'FeatureCollection',
|
||||
features: areaJsonArr
|
||||
}
|
||||
const center = centroid(areaJson)
|
||||
dotData.push({
|
||||
name: area.name,
|
||||
size: d.value,
|
||||
properties: d,
|
||||
x: center.geometry.coordinates[0],
|
||||
y: center.geometry.coordinates[1]
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
if (options.tooltip && options.tooltip.showComponent) {
|
||||
options.tooltip.items = ['name', 'adcode', 'value']
|
||||
options.tooltip.customTitle = ({ name }) => {
|
||||
return name
|
||||
}
|
||||
const formatterMap = tooltip.seriesTooltipFormatter
|
||||
?.filter(i => i.show)
|
||||
.reduce((pre, next) => {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
options.tooltip.customItems = originalItem => {
|
||||
const result = []
|
||||
if (isEmpty(formatterMap)) {
|
||||
return result
|
||||
}
|
||||
const head = originalItem.properties
|
||||
const formatter = formatterMap[head.quotaList?.[0]?.id]
|
||||
if (!isEmpty(formatter)) {
|
||||
const originValue = parseFloat(head.value as string)
|
||||
const value = valueFormatter(originValue, formatter.formatterCfg)
|
||||
const name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
|
||||
result.push({ ...head, name, value: `${value ?? ''}` })
|
||||
}
|
||||
head.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: `${value ?? ''}` })
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
options.tooltip.domStyles = {
|
||||
'l7plot-tooltip': {
|
||||
'background-color': tooltip.backgroundColor,
|
||||
'font-size': `${tooltip.fontSize}px`,
|
||||
'line-height': 1.6
|
||||
},
|
||||
'l7plot-tooltip__name': {
|
||||
color: tooltip.color
|
||||
},
|
||||
'l7plot-tooltip__value': {
|
||||
color: tooltip.color
|
||||
},
|
||||
'l7plot-tooltip__title': {
|
||||
color: tooltip.color
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const areaMap = chart.data?.data?.reduce((obj, value) => {
|
||||
obj[value['field']] = { value: value.value, data: value }
|
||||
return obj
|
||||
}, {})
|
||||
geoJson.features.forEach(item => {
|
||||
const name = item.properties['name']
|
||||
if (areaMap?.[name]?.value) {
|
||||
dotData.push({
|
||||
x: item.properties['centroid'][0],
|
||||
y: item.properties['centroid'][1],
|
||||
size: areaMap[name].value,
|
||||
properties: areaMap[name].data,
|
||||
name: name
|
||||
})
|
||||
}
|
||||
})
|
||||
tooltip: {}
|
||||
}
|
||||
if (bubbleCfg && bubbleCfg.enable) {
|
||||
return new Dot({
|
||||
@ -375,91 +247,6 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
return options
|
||||
}
|
||||
|
||||
protected configCustomArea(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
context: Record<string, any>
|
||||
): ChoroplethOptions {
|
||||
const { drawOption, customSubArea, geoJson } = context
|
||||
if (!drawOption.areaId.startsWith('custom_')) {
|
||||
return options
|
||||
}
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const { label } = customAttr
|
||||
const data = chart.data?.data
|
||||
const areaMap = data?.reduce((obj, value) => {
|
||||
obj[value['field']] = value
|
||||
return obj
|
||||
}, {})
|
||||
//处理label
|
||||
options.label = false
|
||||
if (label.show) {
|
||||
const geoJsonMap = geoJson.features.reduce((p, n) => {
|
||||
if (n.properties['adcode']) {
|
||||
p['156' + n.properties['adcode']] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
const { areaMapping } = parseJson(chart.senior)
|
||||
const labelLocation = []
|
||||
customSubArea.forEach(area => {
|
||||
const areaJsonArr = []
|
||||
area.scopeArr?.forEach(adcode => {
|
||||
const json = geoJsonMap[adcode]
|
||||
json && areaJsonArr.push(json)
|
||||
})
|
||||
if (areaJsonArr.length) {
|
||||
const areaJson: FeatureCollection = {
|
||||
type: 'FeatureCollection',
|
||||
features: areaJsonArr
|
||||
}
|
||||
const content = []
|
||||
if (label.showDimension) {
|
||||
const mappedName = areaMapping?.[drawOption.areaId]?.[area.name]
|
||||
if (mappedName) {
|
||||
area.name = mappedName
|
||||
}
|
||||
content.push(area.name)
|
||||
}
|
||||
if (label.showQuota) {
|
||||
areaMap[area.name] &&
|
||||
content.push(valueFormatter(areaMap[area.name].value, label.quotaLabelFormatter))
|
||||
}
|
||||
const center = centroid(areaJson)
|
||||
labelLocation.push({
|
||||
name: content.join('\n\n'),
|
||||
x: center.geometry.coordinates[0],
|
||||
y: center.geometry.coordinates[1]
|
||||
})
|
||||
}
|
||||
})
|
||||
const areaLabelLayer = new TextLayer({
|
||||
name: 'areaLabelLayer',
|
||||
source: {
|
||||
data: labelLocation,
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'x',
|
||||
y: 'y'
|
||||
}
|
||||
},
|
||||
field: 'name',
|
||||
zIndex: 0.06,
|
||||
style: {
|
||||
fill: label.color,
|
||||
fontSize: label.fontSize,
|
||||
opacity: 1,
|
||||
fontWeight: 'bold',
|
||||
textAnchor: 'center',
|
||||
textAllowOverlap: label.fullDisplay,
|
||||
padding: !label.fullDisplay ? [2, 2] : undefined
|
||||
}
|
||||
})
|
||||
context.layers = [areaLabelLayer]
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
protected setupOptions(
|
||||
chart: Chart,
|
||||
options: ChoroplethOptions,
|
||||
@ -470,8 +257,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
this.configLabel,
|
||||
this.configStyle,
|
||||
this.configTooltip,
|
||||
this.configBasicStyle,
|
||||
this.configCustomArea
|
||||
)(chart, options, context, this)
|
||||
this.configBasicStyle
|
||||
)(chart, options, context)
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,12 +99,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
p['156' + n.properties.adcode] = n.properties.name
|
||||
return p
|
||||
}, {})
|
||||
const { areaMapping } = parseJson(chart.senior)
|
||||
const areaMap = customSubArea.reduce((p, n) => {
|
||||
const mappedName = areaMapping?.[areaId]?.[n.name]
|
||||
if (mappedName) {
|
||||
n.name = mappedName
|
||||
}
|
||||
p[n.name] = n
|
||||
n.scopeArr = n.scope?.split(',') || []
|
||||
return p
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { RadarOptions, Radar as G2Radar } from '@antv/g2plot/esm/plots/radar'
|
||||
import { G2PlotChartView, G2PlotDrawOptions } from '../../types/impl/g2plot'
|
||||
import { flow, parseJson } from '../../../util'
|
||||
import { configPlotTooltipEvent } from '../../common/common_antv'
|
||||
import { configPlotTooltipEvent, getPadding } from '../../common/common_antv'
|
||||
import { valueFormatter } from '../../../formatter'
|
||||
import type { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
@ -25,15 +25,7 @@ export class Radar extends G2PlotChartView<RadarOptions, G2Radar> {
|
||||
'linkage'
|
||||
]
|
||||
propertyInner: EditorPropertyInner = {
|
||||
'basic-style-selector': [
|
||||
'colors',
|
||||
'alpha',
|
||||
'radarShape',
|
||||
'seriesColor',
|
||||
'radarShowPoint',
|
||||
'radarPointSize',
|
||||
'radarAreaColor'
|
||||
],
|
||||
'basic-style-selector': ['colors', 'alpha', 'radarShape', 'seriesColor'],
|
||||
'label-selector': ['seriesLabelFormatter'],
|
||||
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
|
||||
'misc-style-selector': ['showName', 'color', 'fontSize', 'axisColor', 'axisValue'],
|
||||
@ -82,6 +74,13 @@ export class Radar extends G2PlotChartView<RadarOptions, G2Radar> {
|
||||
yField: 'value',
|
||||
seriesField: 'category',
|
||||
appendPadding: [10, 10, 10, 10],
|
||||
point: {
|
||||
size: 4,
|
||||
shape: 'circle',
|
||||
style: {
|
||||
fill: null
|
||||
}
|
||||
},
|
||||
interactions: [
|
||||
{
|
||||
type: 'legend-active',
|
||||
@ -123,22 +122,6 @@ export class Radar extends G2PlotChartView<RadarOptions, G2Radar> {
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configBasicStyle(chart: Chart, options: RadarOptions): RadarOptions {
|
||||
const { radarShowPoint, radarPointSize, radarAreaColor } = parseJson(
|
||||
chart.customAttr
|
||||
).basicStyle
|
||||
const tempOptions: RadarOptions = {}
|
||||
|
||||
if (radarShowPoint) {
|
||||
tempOptions['point'] = { shape: 'circle', size: radarPointSize, style: { fill: null } }
|
||||
}
|
||||
if (radarAreaColor) {
|
||||
tempOptions['area'] = {}
|
||||
}
|
||||
|
||||
return { ...options, ...tempOptions }
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: RadarOptions): RadarOptions {
|
||||
const tmpOptions = super.configLabel(chart, options)
|
||||
if (!tmpOptions.label) {
|
||||
@ -283,8 +266,7 @@ export class Radar extends G2PlotChartView<RadarOptions, G2Radar> {
|
||||
this.configLabel,
|
||||
this.configLegend,
|
||||
this.configMultiSeriesTooltip,
|
||||
this.configAxis,
|
||||
this.configBasicStyle
|
||||
this.configAxis
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import {
|
||||
S2Event,
|
||||
S2Options,
|
||||
S2Theme,
|
||||
ScrollbarPositionType,
|
||||
TableColCell,
|
||||
TableSheet,
|
||||
ViewMeta
|
||||
@ -23,8 +22,7 @@ import {
|
||||
calculateHeaderHeight,
|
||||
SortTooltip,
|
||||
configSummaryRow,
|
||||
summaryRowStyle,
|
||||
configEmptyDataStyle
|
||||
summaryRowStyle
|
||||
} from '@/views/chart/components/js/panel/common/common_table'
|
||||
|
||||
const { t } = useI18n()
|
||||
@ -169,10 +167,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
renderTooltip: sheet => new SortTooltip(sheet)
|
||||
},
|
||||
interaction: {
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false),
|
||||
scrollbarPosition: newData.length
|
||||
? ScrollbarPositionType.CONTENT
|
||||
: ScrollbarPositionType.CANVAS
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false)
|
||||
}
|
||||
}
|
||||
s2Options.style = this.configStyle(chart, s2DataConfig)
|
||||
@ -186,7 +181,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
return p
|
||||
}, {})
|
||||
}
|
||||
if (tableCell.tableFreeze && !tableCell.mergeCells) {
|
||||
if (tableCell.tableFreeze) {
|
||||
s2Options.frozenColCount = tableCell.tableColumnFreezeHead ?? 0
|
||||
s2Options.frozenRowCount = tableCell.tableRowFreezeHead ?? 0
|
||||
}
|
||||
@ -217,7 +212,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
viewMeta.autoWrap = basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
@ -244,7 +239,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
this.configHeaderInteraction(chart, s2Options)
|
||||
s2Options.colCell = (node, sheet, config) => {
|
||||
// 配置文本自动换行参数
|
||||
node.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
node.autoWrap = basicStyle.autoWrap
|
||||
node.maxLines = basicStyle.maxLines
|
||||
return new CustomTableColCell(node, sheet, config)
|
||||
}
|
||||
@ -256,7 +251,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
// 总计紧贴在单元格后面
|
||||
summaryRowStyle(newChart, newData, tableCell, tableHeader, basicStyle.showSummary)
|
||||
// 开启自动换行
|
||||
if (basicStyle.autoWrap && !tableCell.mergeCells) {
|
||||
if (basicStyle.autoWrap) {
|
||||
// 调整表头宽度时,计算表头高度
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, info => {
|
||||
calculateHeaderHeight(info, newChart, tableHeader, basicStyle, null)
|
||||
@ -340,8 +335,6 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
ev.colsHierarchy.width = containerWidth
|
||||
})
|
||||
}
|
||||
// 空数据时表格样式
|
||||
configEmptyDataStyle(newChart, basicStyle, newData, container)
|
||||
// click
|
||||
newChart.on(S2Event.DATA_CELL_CLICK, ev => {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { formatterItem, valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import {
|
||||
configEmptyDataStyle,
|
||||
configSummaryRow,
|
||||
copyContent,
|
||||
SortTooltip,
|
||||
@ -14,7 +13,6 @@ import {
|
||||
S2DataConfig,
|
||||
S2Event,
|
||||
S2Options,
|
||||
ScrollbarPositionType,
|
||||
TableColCell,
|
||||
TableSheet,
|
||||
ViewMeta
|
||||
@ -147,10 +145,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
renderTooltip: sheet => new SortTooltip(sheet)
|
||||
},
|
||||
interaction: {
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false),
|
||||
scrollbarPosition: newData.length
|
||||
? ScrollbarPositionType.CONTENT
|
||||
: ScrollbarPositionType.CANVAS
|
||||
hoverHighlight: !(basicStyle.showHoverStyle === false)
|
||||
}
|
||||
}
|
||||
// 列宽设置
|
||||
@ -247,7 +242,6 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
ev.colsHierarchy.width = containerWidth
|
||||
})
|
||||
}
|
||||
configEmptyDataStyle(newChart, basicStyle, newData, container)
|
||||
// click
|
||||
newChart.on(S2Event.DATA_CELL_CLICK, ev => {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
|
||||
@ -176,10 +176,6 @@ export function getLabel(chart: Chart) {
|
||||
) {
|
||||
layout.push({ type: 'limit-in-canvas' })
|
||||
layout.push({ type: 'hide-overlap' })
|
||||
} else if (chart.type.includes('chart-mix')) {
|
||||
layout.push({ type: 'limit-in-canvas' })
|
||||
layout.push({ type: 'limit-in-plot' })
|
||||
layout.push({ type: 'hide-overlap' })
|
||||
} else {
|
||||
layout.push({ type: 'limit-in-plot' })
|
||||
layout.push({ type: 'fixed-overlap' })
|
||||
@ -560,8 +556,7 @@ export function getYAxis(chart: Chart) {
|
||||
grid,
|
||||
label,
|
||||
line,
|
||||
tickLine,
|
||||
nice: true
|
||||
tickLine
|
||||
}
|
||||
return axis
|
||||
}
|
||||
@ -654,8 +649,7 @@ export function getYAxisExt(chart: Chart) {
|
||||
grid,
|
||||
label,
|
||||
line,
|
||||
tickLine,
|
||||
nice: true
|
||||
tickLine
|
||||
}
|
||||
return axis
|
||||
}
|
||||
|
||||
@ -1671,7 +1671,6 @@ const drawTextShape = (cell, isHeader) => {
|
||||
* @param layoutResult
|
||||
*/
|
||||
export const calculateHeaderHeight = (info, newChart, tableHeader, basicStyle, layoutResult) => {
|
||||
if (tableHeader.showTableHeader === false ) return
|
||||
const ev = layoutResult || newChart.facet.layoutResult
|
||||
const maxLines = basicStyle.maxLines ?? 1
|
||||
const textStyle = { ...newChart.theme.cornerCell.text }
|
||||
@ -1764,7 +1763,7 @@ const getWrapTextHeight = (wrapText, textStyle, spreadsheet, maxLines) => {
|
||||
* @param showSummary
|
||||
*/
|
||||
export const configSummaryRow = (chart, s2Options, newData, tableHeader, basicStyle, showSummary) =>{
|
||||
if (!showSummary || !newData.length) return
|
||||
if (!showSummary) return
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[newData.length] = tableHeader.tableTitleHeight
|
||||
@ -1822,13 +1821,10 @@ export const configSummaryRow = (chart, s2Options, newData, tableHeader, basicSt
|
||||
* @param showSummary
|
||||
*/
|
||||
export const summaryRowStyle = (newChart, newData, tableCell, tableHeader, showSummary) => {
|
||||
if (!showSummary || !newData.length) return
|
||||
if (!showSummary) return
|
||||
newChart.on(S2Event.LAYOUT_BEFORE_RENDER, () => {
|
||||
const showHeader = tableHeader.showTableHeader === true
|
||||
// 不显示表头时,减少一个表头的高度
|
||||
const headerAndSummaryHeight = showHeader ? 2 : 1
|
||||
const totalHeight =
|
||||
tableHeader.tableTitleHeight * headerAndSummaryHeight + tableCell.tableItemHeight * (newData.length - 1)
|
||||
tableHeader.tableTitleHeight * 2 + tableCell.tableItemHeight * (newData.length - 1)
|
||||
if (totalHeight < newChart.options.height) {
|
||||
// 6 是阴影高度
|
||||
newChart.options.height =
|
||||
@ -1848,41 +1844,3 @@ export class SummaryCell extends CustomDataCell {
|
||||
return { backgroundColor, backgroundColorOpacity }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置空数据样式
|
||||
* @param newChart
|
||||
* @param basicStyle
|
||||
* @param newData
|
||||
* @param container
|
||||
*/
|
||||
export const configEmptyDataStyle = (newChart, basicStyle, newData, container) => {
|
||||
/**
|
||||
* 辅助函数:移除空数据dom
|
||||
*/
|
||||
const removeEmptyDom = () => {
|
||||
const emptyElement = document.getElementById(container + '_empty')
|
||||
if (emptyElement) {
|
||||
emptyElement.parentElement.removeChild(emptyElement)
|
||||
}
|
||||
}
|
||||
removeEmptyDom()
|
||||
if (newData.length) return
|
||||
newChart.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev) => {
|
||||
removeEmptyDom()
|
||||
if (!newData.length) {
|
||||
const emptyDom = document.createElement('div')
|
||||
const left = Math.min(newChart.options.width, ev.colsHierarchy.width) / 2 - 32
|
||||
emptyDom.id = container + '_empty'
|
||||
emptyDom.textContent = t('data_set.no_data')
|
||||
emptyDom.setAttribute(
|
||||
'style',
|
||||
`position: absolute;
|
||||
left: ${left}px;
|
||||
top: 50%;`
|
||||
)
|
||||
const parent = document.getElementById(container)
|
||||
parent.insertBefore(emptyDom, parent.firstChild)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -183,7 +183,6 @@ const calcData = async (view, callback) => {
|
||||
emit('onDrillFilters', res?.drillFilters)
|
||||
if (!res?.drillFilters?.length) {
|
||||
dynamicAreaId.value = ''
|
||||
scope = null
|
||||
} else {
|
||||
const extra = view.chartExtRequest?.drill?.[res?.drillFilters?.length - 1].extra
|
||||
dynamicAreaId.value = extra?.adcode + ''
|
||||
|
||||
@ -22,7 +22,7 @@ import { storeToRefs } from 'pinia'
|
||||
import { S2ChartView } from '@/views/chart/components/js/panel/types/impl/s2'
|
||||
import { ElPagination } from 'element-plus-secondary'
|
||||
import ChartError from '@/views/chart/components/views/components/ChartError.vue'
|
||||
import { defaultsDeep, cloneDeep, debounce } from 'lodash-es'
|
||||
import { defaultsDeep, cloneDeep } from 'lodash-es'
|
||||
import { BASE_VIEW_CONFIG } from '../../editor/util/chart'
|
||||
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
@ -193,31 +193,29 @@ const renderChart = (viewInfo: Chart, resetPageInfo: boolean) => {
|
||||
recursionTransObj(customAttrTrans, actualChart.customAttr, scale.value, terminal.value)
|
||||
recursionTransObj(customStyleTrans, actualChart.customStyle, scale.value, terminal.value)
|
||||
|
||||
setupPage(actualChart, resetPageInfo)
|
||||
nextTick(() => debounceRender(resetPageInfo))
|
||||
}
|
||||
|
||||
const debounceRender = debounce(resetPageInfo => {
|
||||
myChart?.facet?.timer?.stop()
|
||||
myChart?.facet?.cancelScrollFrame()
|
||||
myChart?.destroy()
|
||||
myChart?.getCanvasElement()?.remove()
|
||||
myChart = null
|
||||
setupPage(actualChart, resetPageInfo)
|
||||
const chartView = chartViewManager.getChartView(
|
||||
actualChart.render,
|
||||
actualChart.type
|
||||
viewInfo.render,
|
||||
viewInfo.type
|
||||
) as S2ChartView<any>
|
||||
myChart = chartView.drawChart({
|
||||
container: containerId,
|
||||
chart: toRaw(actualChart),
|
||||
chartObj: myChart,
|
||||
pageInfo: state.pageInfo,
|
||||
action,
|
||||
resizeAction
|
||||
})
|
||||
myChart?.render()
|
||||
dvMainStore.setViewInstanceInfo(actualChart.id, myChart)
|
||||
initScroll()
|
||||
}, 500)
|
||||
timer = setTimeout(() => {
|
||||
myChart = chartView.drawChart({
|
||||
container: containerId,
|
||||
chart: toRaw(actualChart),
|
||||
chartObj: myChart,
|
||||
pageInfo: state.pageInfo,
|
||||
action,
|
||||
resizeAction
|
||||
})
|
||||
myChart?.render()
|
||||
dvMainStore.setViewInstanceInfo(viewInfo.id, myChart)
|
||||
initScroll()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
|
||||
const customAttr = chart.customAttr
|
||||
@ -583,12 +581,24 @@ const resize = (width, height) => {
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
if (!myChart?.facet) {
|
||||
debounceRender(false)
|
||||
const chartView = chartViewManager.getChartView(
|
||||
actualChart.render,
|
||||
actualChart.type
|
||||
) as S2ChartView<any>
|
||||
myChart = chartView.drawChart({
|
||||
container: containerId,
|
||||
chart: toRaw(actualChart),
|
||||
chartObj: myChart,
|
||||
pageInfo: state.pageInfo,
|
||||
action,
|
||||
resizeAction
|
||||
})
|
||||
dvMainStore.setViewInstanceInfo(actualChart.id, myChart)
|
||||
} else {
|
||||
myChart?.facet?.timer?.stop()
|
||||
myChart?.changeSheetSize(width, height)
|
||||
myChart?.render()
|
||||
}
|
||||
myChart?.render()
|
||||
initScroll()
|
||||
}, 500)
|
||||
}
|
||||
@ -610,7 +620,7 @@ onMounted(() => {
|
||||
}
|
||||
preSize[0] = size.inlineSize
|
||||
preSize[1] = size.blockSize
|
||||
resize(size.inlineSize, Math.round(size.blockSize))
|
||||
resize(size.inlineSize, Math.ceil(size.blockSize))
|
||||
})
|
||||
|
||||
resizeObserver.observe(document.getElementById(containerId))
|
||||
|
||||
@ -67,15 +67,10 @@ const loadThemeStyle = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
const drillPathVar = computed(() => [{ '--drill-color': textColor.value }])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="props.drillFilters && props.drillFilters.length > 0"
|
||||
class="drill"
|
||||
:style="drillPathVar"
|
||||
>
|
||||
<div v-if="props.drillFilters && props.drillFilters.length > 0" class="drill">
|
||||
<el-breadcrumb :separator-icon="ArrowRight" class="drill-style">
|
||||
<el-breadcrumb-item class="drill-item" @click="drillJump(0)">
|
||||
<span :style="{ color: textColor }">{{ t('commons.all') }}</span>
|
||||
@ -115,8 +110,5 @@ const drillPathVar = computed(() => [{ '--drill-color': textColor.value }])
|
||||
z-index: 1;
|
||||
height: 20px;
|
||||
padding: 0 16px;
|
||||
::v-deep(.ed-icon) {
|
||||
color: var(--drill-color) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1067,24 +1067,14 @@ const titleTooltipWidth = computed(() => {
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:effect="toolTip"
|
||||
placement="top"
|
||||
:content="t('visualization.jump_set_tips')"
|
||||
v-if="hasJumpIcon"
|
||||
>
|
||||
<el-tooltip :effect="toolTip" placement="top" content="已设置跳转" v-if="hasJumpIcon">
|
||||
<el-icon :size="iconSize" class="inner-icon">
|
||||
<Icon name="icon_viewinchat_outlined"
|
||||
><icon_viewinchat_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:effect="toolTip"
|
||||
placement="top"
|
||||
:content="t('visualization.drill_set_tips')"
|
||||
v-if="hasDrillIcon"
|
||||
>
|
||||
<el-tooltip :effect="toolTip" placement="top" content="已设置下钻" v-if="hasDrillIcon">
|
||||
<el-icon :size="iconSize" class="inner-icon">
|
||||
<Icon name="icon_drilling_outlined"><icon_drilling_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
|
||||
@ -141,8 +141,8 @@ const optInit = (type, data: BusiTreeNode, exec, parentSelect = false) => {
|
||||
const placeholderLabel =
|
||||
data.leaf || type === 'leaf'
|
||||
? props.curCanvasType === 'dataV'
|
||||
? t('work_branch.screen')
|
||||
: t('work_branch.dashboard')
|
||||
? t('visualization.screen')
|
||||
: t('visualization.dashboard')
|
||||
: t('visualization.folder')
|
||||
placeholder.value = t('visualization.input_name_tips', [placeholderLabel])
|
||||
filterText.value = ''
|
||||
|
||||
@ -321,7 +321,7 @@ const save = () => {
|
||||
<el-tab-pane :label="t('visualization.visualization_component')" name="com"> </el-tab-pane>
|
||||
<el-tab-pane :label="t('visualization.component_style')" name="componentStyle">
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('visualization.whole_style')" name="style"> </el-tab-pane>
|
||||
<el-tab-pane label="t('visualization.whole_style')" name="style"> </el-tab-pane>
|
||||
</el-tabs>
|
||||
<template v-if="!mobileLoading">
|
||||
<div class="config-mobile-tab" v-show="activeCollapse === 'style'">
|
||||
|
||||
@ -168,8 +168,8 @@ const XpackLoaded = () => p(true)
|
||||
onMounted(async () => {
|
||||
useEmitt({
|
||||
name: 'canvasDownload',
|
||||
callback: function (type = 'img') {
|
||||
downloadH2(type)
|
||||
callback: function () {
|
||||
downloadH2('img')
|
||||
}
|
||||
})
|
||||
await new Promise(r => (p = r))
|
||||
|
||||
@ -34,7 +34,7 @@ const favorited = ref(false)
|
||||
const preview = () => {
|
||||
const baseUrl = isDataEaseBi.value ? embeddedStore.baseUrl : ''
|
||||
const url = baseUrl + '#/preview?dvId=' + dvInfo.value.id + '&ignoreParams=true'
|
||||
const newWindow = window.open(url, '_blank')
|
||||
const newWindow = window.open(url, openType)
|
||||
initOpenHandler(newWindow)
|
||||
}
|
||||
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
|
||||
|
||||
@ -342,7 +342,6 @@ const newWindowFromDiv = ref(false)
|
||||
let p = null
|
||||
const XpackLoaded = () => p(true)
|
||||
onMounted(async () => {
|
||||
snapshotStore.initSnapShot()
|
||||
if (window.location.hash.includes('#/dvCanvas')) {
|
||||
newWindowFromDiv.value = true
|
||||
}
|
||||
@ -429,8 +428,6 @@ onMounted(async () => {
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('storage', eventCheck)
|
||||
window.removeEventListener('blur', releaseAttachKey)
|
||||
eventBus.off('handleNew', handleNew)
|
||||
eventBus.off('tabSort', tabSort)
|
||||
})
|
||||
|
||||
const previewStatus = computed(() => editMode.value === 'preview')
|
||||
|
||||
@ -147,7 +147,7 @@
|
||||
</div>
|
||||
|
||||
<div class="ticket-btn">
|
||||
<el-button type="primary" @click.stop="finish"> {{ $t('components.complete') }} </el-button>
|
||||
<el-button type="primary" @click.stop="finish"> 完成 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,19 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, PropType } from 'vue'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage, ElLoading } from 'element-plus-secondary'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import type { FormInstance, FormRules } from 'element-plus-secondary'
|
||||
import request from '@/config/axios'
|
||||
import dvInfo from '@/assets/svg/dv-info.svg'
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
labelTooltips: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const loadingInstance = ref(null)
|
||||
const basicForm = ref<FormInstance>()
|
||||
@ -57,14 +48,6 @@ const state = reactive({
|
||||
]
|
||||
})
|
||||
|
||||
const tooltipItem = ref({})
|
||||
const formatLabel = () => {
|
||||
props.labelTooltips?.length &&
|
||||
props.labelTooltips.forEach(tooltip => {
|
||||
tooltipItem.value[tooltip.key] = tooltip.val
|
||||
})
|
||||
}
|
||||
|
||||
const rule = reactive<FormRules>({
|
||||
dsIntervalTime: [
|
||||
{
|
||||
@ -246,7 +229,6 @@ const oidChange = () => {
|
||||
state.form['platformRid'] = []
|
||||
loadRoleOptions()
|
||||
}
|
||||
formatLabel()
|
||||
defineExpose({
|
||||
edit
|
||||
})
|
||||
@ -273,22 +255,8 @@ defineExpose({
|
||||
:key="item.pkey"
|
||||
:prop="item.pkey"
|
||||
:class="{ 'setting-hidden-item': item.pkey === 'dsExecuteTime' }"
|
||||
:label="t(item.label)"
|
||||
>
|
||||
<template v-slot:label>
|
||||
<div class="basic-form-info-tips">
|
||||
<span class="custom-form-item__label">{{ t(item.label) }}</span>
|
||||
<el-tooltip
|
||||
v-if="tooltipItem[`setting_basic.${item.pkey}`]"
|
||||
effect="dark"
|
||||
:content="tooltipItem[`setting_basic.${item.pkey}`]"
|
||||
placement="top"
|
||||
>
|
||||
<el-icon
|
||||
><Icon name="dv-info"><dvInfo class="svg-icon" /></Icon
|
||||
></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch
|
||||
class="de-basic-switch"
|
||||
v-if="
|
||||
@ -451,32 +419,6 @@ defineExpose({
|
||||
.ed-form-item__label {
|
||||
line-height: 22px !important;
|
||||
height: 22px !important;
|
||||
|
||||
.basic-form-info-tips {
|
||||
width: fit-content;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
column-gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.ed-form-item {
|
||||
&.is-required.asterisk-right {
|
||||
.ed-form-item__label:after {
|
||||
display: none;
|
||||
}
|
||||
.basic-form-info-tips {
|
||||
.custom-form-item__label:after {
|
||||
content: '*';
|
||||
color: var(--ed-color-danger);
|
||||
margin-left: 2px;
|
||||
font-family: var(--de-custom_font, 'PingFang');
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ed-radio__label {
|
||||
font-weight: 400;
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
"
|
||||
/>
|
||||
<InfoTemplate
|
||||
v-if="loginInoSettings?.length"
|
||||
ref="loginTemplate"
|
||||
class="login-setting-template"
|
||||
:label-tooltips="tooltips"
|
||||
@ -29,7 +28,6 @@
|
||||
/>
|
||||
|
||||
<InfoTemplate
|
||||
v-if="thirdInfoSettings?.length"
|
||||
ref="thirdTemplate"
|
||||
class="login-setting-template"
|
||||
:label-tooltips="tooltips"
|
||||
@ -43,7 +41,7 @@
|
||||
)
|
||||
"
|
||||
/>
|
||||
<basic-edit ref="editor" :label-tooltips="tooltips" @saved="refresh" />
|
||||
<basic-edit ref="editor" @saved="refresh" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -251,9 +249,9 @@ const search = cb => {
|
||||
const refresh = () => {
|
||||
search(() => {
|
||||
nextTick(() => {
|
||||
infoTemplate?.value?.init()
|
||||
loginTemplate?.value?.init()
|
||||
thirdTemplate?.value?.init()
|
||||
infoTemplate?.value.init()
|
||||
loginTemplate?.value.init()
|
||||
thirdTemplate?.value.init()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -150,8 +150,8 @@
|
||||
</div>
|
||||
<div class="sub-area-view" v-else>
|
||||
<div id="map-container" class="map-container"></div>
|
||||
<el-divider />
|
||||
<div class="sub-area-editor">
|
||||
<el-divider />
|
||||
<span class="header">
|
||||
<span class="label">
|
||||
<span>自定义区域</span>
|
||||
@ -164,7 +164,7 @@
|
||||
<span>添加区域</span>
|
||||
</span>
|
||||
</span>
|
||||
<el-table :data="subAreaList" stripe style="width: 100%" :height="300">
|
||||
<el-table :data="subAreaList" stripe style="width: 100%">
|
||||
<el-table-column prop="name" label="区域名称">
|
||||
<template #default="{ row, $index }">
|
||||
<span
|
||||
@ -593,7 +593,13 @@ const mapOption: ChoroplethOptions = {
|
||||
lineWidth: 0.6,
|
||||
lineOpacity: 1
|
||||
},
|
||||
label: false,
|
||||
label: {
|
||||
field: 'name',
|
||||
style: {
|
||||
fill: 'black',
|
||||
textAnchor: 'center'
|
||||
}
|
||||
},
|
||||
state: {
|
||||
active: { stroke: 'green', lineWidth: 1 }
|
||||
},
|
||||
@ -650,8 +656,7 @@ const renderMap = async () => {
|
||||
fontSize: 20,
|
||||
opacity: 1,
|
||||
fontWeight: 'bold',
|
||||
textAnchor: 'center',
|
||||
textAllowOverlap: true
|
||||
textAnchor: 'center'
|
||||
}
|
||||
})
|
||||
if (mapInstance) {
|
||||
@ -667,7 +672,7 @@ const renderMap = async () => {
|
||||
value: area => {
|
||||
let color = 'white'
|
||||
subAreaList.value?.forEach((subArea, i) => {
|
||||
if (subArea.scopeArr?.includes('156' + area.adcode)) {
|
||||
if (subArea.scope?.includes(area.adcode)) {
|
||||
color = AREA_COLOR[i % AREA_COLOR.length]
|
||||
}
|
||||
})
|
||||
@ -840,17 +845,16 @@ onBeforeMount(() => {
|
||||
.sub-area-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
width: 100;
|
||||
height: 100%;
|
||||
.map-container {
|
||||
flex: 1;
|
||||
flex: 7;
|
||||
}
|
||||
.ed-divider {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.sub-area-editor {
|
||||
height: 350px;
|
||||
flex: 3;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit 13ecdfab148086cf6e66fed2bcb41d88fdd5efab
|
||||
Subproject commit fd3d8b68af7560e817c7043933320289f79b0175
|
||||
@ -371,7 +371,6 @@ function restore() {
|
||||
mkdir -p $DE_RUNNING_BASE
|
||||
fi
|
||||
echo "恢复备份 $target"
|
||||
rm -rf $DE_RUNNING_BASE/data/mysql/*
|
||||
tar -zxf $target --directory=$DE_RUNNING_BASE
|
||||
service dataease start
|
||||
else
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -19,7 +19,7 @@
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<dataease.version>2.10.3</dataease.version>
|
||||
<dataease.version>2.10.2</dataease.version>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package io.dataease.api.rmonitor;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
public interface ResourceMonitorApi {
|
||||
|
||||
@GetMapping("/existFree")
|
||||
boolean existFree();
|
||||
|
||||
@PostMapping("/delete")
|
||||
void delete();
|
||||
|
||||
@PostMapping("/sync")
|
||||
void sync();
|
||||
}
|
||||
@ -3,7 +3,10 @@ package io.dataease.api.permissions.auth.api;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.api.permissions.auth.dto.*;
|
||||
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
|
||||
import io.dataease.api.permissions.auth.dto.BusiResourceCreator;
|
||||
import io.dataease.api.permissions.auth.dto.BusiResourceEditor;
|
||||
import io.dataease.api.permissions.auth.dto.BusiResourceMover;
|
||||
import io.dataease.api.permissions.auth.vo.PermissionValVO;
|
||||
import io.dataease.api.permissions.auth.vo.ResourceNodeVO;
|
||||
import io.dataease.model.BusiNodeRequest;
|
||||
@ -86,7 +89,4 @@ public interface InteractiveAuthApi {
|
||||
String OrgNameForResource(ExportTaskDTO exportTaskDTO);
|
||||
|
||||
void editResourceExtraFlag(BusiResourceEditor editor);
|
||||
|
||||
@PostMapping("/batchAuthorize")
|
||||
void batchAuthorize(@RequestBody BusiBatchAuthorizeRequest request);
|
||||
}
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
package io.dataease.api.permissions.auth.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BusiBatchAuthorizeNode implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 5804450226135199435L;
|
||||
private List<Long> idList;
|
||||
|
||||
private int flag;
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package io.dataease.api.permissions.auth.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BusiBatchAuthorizeRequest implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5219199153835271350L;
|
||||
|
||||
private List<BusiBatchAuthorizeNode> nodeList;
|
||||
|
||||
private Long oid;
|
||||
}
|
||||
@ -15,9 +15,6 @@ import java.util.List;
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Value("${dataease.cors-strict:false}")
|
||||
private boolean corsStrict;
|
||||
|
||||
|
||||
@Value("#{'${dataease.origin-list:http://127.0.0.1:8100}'.split(',')}")
|
||||
private List<String> originList;
|
||||
@ -32,19 +29,15 @@ public class CorsConfig implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
operateCorsRegistration = registry.addMapping("/**")
|
||||
.allowCredentials(false)
|
||||
.allowCredentials(true)
|
||||
.allowedOrigins(originList.toArray(new String[0]))
|
||||
.allowedHeaders("*")
|
||||
.maxAge(3600)
|
||||
.allowedMethods("GET", "POST", "DELETE");
|
||||
if (corsStrict) {
|
||||
operateCorsRegistration.allowedOrigins(originList.toArray(new String[0]));
|
||||
return;
|
||||
}
|
||||
operateCorsRegistration.allowedOrigins("*");
|
||||
}
|
||||
|
||||
public void addAllowedOrigins(List<String> origins) {
|
||||
if (!corsStrict || CollectionUtils.isEmpty(origins)) {
|
||||
if (CollectionUtils.isEmpty(origins)) {
|
||||
return;
|
||||
}
|
||||
origins.addAll(originList);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user