Merge branch 'dev-v2' into pr@dev-v2@refactor_label

This commit is contained in:
王嘉豪 2023-12-27 15:30:46 +08:00 committed by GitHub
commit 2a7655e885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
224 changed files with 2344 additions and 1057 deletions

8
.gitattributes vendored
View File

@ -1 +1,9 @@
*.sql linguist-language=java
*.java linguist-language=Java
*.md linguist-language=Java
*.yml linguist-language=Java
*.html linguist-language=Java
*.js linguist-language=Java
*.xml linguist-language=Java
*.css linguist-language=Java
*.ts linguist-language=Java

View File

@ -3,7 +3,7 @@ name: Bug 提交
about: 提交产品缺陷帮助我们更好的改进
title: "[Bug]"
labels: 状态:待处理
assignees: BBchicken-9527, zrfit
assignees: BBchicken-9527, Shenguobin0102, zrfit
---

View File

@ -6,11 +6,6 @@
<a href="https://github.com/dataease/dataease"><img src="https://img.shields.io/github/stars/dataease/dataease?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
|说明|
|------------------|
|此分支为 DataEase v2 版本的开发分支DataEase v2 正在快速迭代中如是在生产环境部署 DataEase建议使用 v1.18.* 的最新稳定版本|
<hr/>
## 什么是 DataEase
DataEase 是开源的数据可视化分析工具帮助用户快速分析数据并洞察业务趋势从而实现业务的改进与优化DataEase 支持丰富的数据源连接能够通过拖拉拽方式快速制作图表并可以方便的与他人分享
@ -56,6 +51,7 @@ DataEase 是开源的数据可视化分析工具,帮助用户快速分析数
- [在线文档](https://dataease.io/docs/)
- [社区论坛](https://bbs.fit2cloud.com/c/de/6)
- [快速入门视频](https://www.bilibili.com/video/BV1Z84y1X7eF/)
## License

View File

@ -124,11 +124,11 @@
<phase>generate-resources</phase>
<configuration>
<target>
<move todir="src/main/resources/static">
<copy todir="src/main/resources/static">
<fileset dir="../core-frontend/dist">
<include name="**"/>
</fileset>
</move>
</copy>
</target>
</configuration>
<goals>
@ -137,18 +137,7 @@
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>static/**</include>
</includes>
</resource>
</resources>
</build>
</profile>
@ -207,25 +196,16 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>static/**</include>
</includes>
</resource>
</resources>
</build>
</profile>
<!-- 分布式版(企业版/saas版) -->
<!-- 分布式版(企业版) -->
<profile>
<id>distributed</id>
<properties>
<profiles.active>distributed</profiles.active>
</properties>
<dependencies>
<!-- 分布式版(企业版/saas版) 引入分布式组件 -->
<!-- 分布式版(企业版) 引入分布式组件 -->
<dependency>
<groupId>io.dataease</groupId>
<artifactId>distributed</artifactId>
@ -239,7 +219,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<!-- 分布式版(企业版/saas版) 需要排除权限替补实现 否则就会出现多个权限实现 报错 -->
<!-- 分布式版(企业版) 需要排除权限替补实现 否则就会出现多个权限实现 报错 -->
<exclude>io/dataease/substitute/**</exclude>
</excludes>
</configuration>
@ -262,16 +242,30 @@
<include>**/*.sql</include>
<include>**/*.xlsx</include>
</includes>
<excludes>
<exclude>static/**/*.*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/**/*.*</include>
</includes>
</resource>
</resources>
<!-- springboot打包插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--<configuration>
<mainClass>io.dataease.CoreApplication</mainClass>
</configuration>-->
<executions>
<execution>
<goals>

View File

@ -67,6 +67,8 @@ public class ChartDataManage {
@Resource
private CorePermissionManage corePermissionManage;
public static final String START_END_SEPARATOR = "_START_END_SPLIT";
private static Logger logger = LoggerFactory.getLogger(ChartDataManage.class);
public ChartViewDTO calcData(ChartViewDTO view) throws Exception {
@ -246,7 +248,8 @@ public class ChartDataManage {
List<SqlVariableDetails> sqlVariables = datasetGroupManage.getSqlParams(Arrays.asList(view.getTableId()));
if (CollectionUtil.isNotEmpty(sqlVariables)) {
for (SqlVariableDetails parameter : Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>())) {
if (sqlVariables.stream().map(SqlVariableDetails::getId).collect(Collectors.toList()).contains(parameter.getId())) {
String parameterId = StringUtils.endsWith(parameter.getId(), START_END_SEPARATOR) ? parameter.getId().split(START_END_SEPARATOR)[0] : parameter.getId();
if (sqlVariables.stream().map(SqlVariableDetails::getId).collect(Collectors.toList()).contains(parameterId)) {
hasParameters = true;
}
}

View File

@ -1105,14 +1105,13 @@ public class ChartDataBuild {
desensitizationStr = "*** ***";
break;
}
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() >= columnPermissionItem.getDesensitizationRule().getN()) {
if (columnPermissionItem.getDesensitizationRule().getM() == 1) {
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
break;
} else {
desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
break;
}
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() < columnPermissionItem.getDesensitizationRule().getN()) {
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, originStr.length());
}
break;
default:
break;

View File

@ -20,6 +20,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.dataease.chart.manage.ChartDataManage.START_END_SEPARATOR;
import static org.apache.calcite.sql.SqlKind.*;
public class SqlparserUtils {
@ -166,7 +167,11 @@ public class SqlparserUtils {
return "'" + String.join("','", sqlVariableDetails.getValue()) + "'";
} else if (sqlVariableDetails.getOperator().equals("between")) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sqlVariableDetails.getType().size() > 1 ? (String) sqlVariableDetails.getType().get(1).replace("DD", "dd") : "YYYY");
return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(0))));
if (StringUtils.endsWith(sqlVariableDetails.getId(), START_END_SEPARATOR)) {
return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(1))));
} else {
return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(0))));
}
} else {
return (String) sqlVariableDetails.getValue().get(0);
}

View File

@ -498,4 +498,26 @@ public class DatasetGroupManage {
geFullName(parent.getPid(), fullName);
}
}
public List<DatasetTableDTO> getDetailWithPerm(List<Long> ids) {
var result = new ArrayList<DatasetTableDTO>();
if (CollectionUtil.isNotEmpty(ids)) {
var dsList = coreDatasetGroupMapper.selectBatchIds(ids);
if (CollectionUtil.isNotEmpty(dsList)) {
dsList.forEach(ds -> {
DatasetTableDTO dto = new DatasetTableDTO();
BeanUtils.copyBean(dto, ds);
var fields = datasetTableFieldManage.listFieldsWithPermissions(ds.getId());
List<DatasetTableFieldDTO> dimensionList = fields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "d")).toList();
List<DatasetTableFieldDTO> quotaList = fields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "q")).toList();
Map<String, List<DatasetTableFieldDTO>> map = new LinkedHashMap<>();
map.put("dimensionList", dimensionList);
map.put("quotaList", quotaList);
dto.setFields(map);
result.add(dto);
});
}
}
return result;
}
}

View File

@ -1,6 +1,9 @@
package io.dataease.dataset.manage;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.api.chart.dto.ColumnPermissionItem;
import io.dataease.auth.bo.TokenUserBO;
import io.dataease.dataset.dao.auto.entity.CoreDatasetTableField;
import io.dataease.dataset.dao.auto.mapper.CoreDatasetGroupMapper;
import io.dataease.dataset.dao.auto.mapper.CoreDatasetTableFieldMapper;
@ -9,6 +12,7 @@ import io.dataease.datasource.provider.CalciteProvider;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.dataease.exception.DEException;
import io.dataease.i18n.Translator;
import io.dataease.utils.AuthUtils;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.IDUtils;
import jakarta.annotation.Resource;
@ -18,9 +22,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -187,6 +189,20 @@ public class DatasetTableFieldManage {
return map;
}
public List<DatasetTableFieldDTO> listFieldsWithPermissions(Long id) {
List<DatasetTableFieldDTO> fields = selectByDatasetGroupId(id);
Map<String, ColumnPermissionItem> desensitizationList = new HashMap<>();
Long userId = AuthUtils.getUser() == null ? null : AuthUtils.getUser().getUserId();
List<DatasetTableFieldDTO> tmp = permissionManage
.filterColumnPermissions(fields, desensitizationList, id, userId)
.stream()
.sorted(Comparator.comparing(DatasetTableFieldDTO::getGroupType))
.toList();
tmp.forEach(ele -> ele.setDesensitized(desensitizationList.containsKey(ele.getDataeaseName())));
return tmp;
}
public List<DatasetTableFieldDTO> transDTO(List<CoreDatasetTableField> list) {
return list.stream().map(ele -> {
DatasetTableFieldDTO dto = new DatasetTableFieldDTO();

View File

@ -53,6 +53,11 @@ public class DatasetFieldServer implements DatasetTableApi {
return datasetTableFieldManage.listByDQ(id);
}
@Override
public List<DatasetTableFieldDTO> listFieldsWithPermissions(Long id) {
return datasetTableFieldManage.listFieldsWithPermissions(id);
}
@Override
public List<String> multFieldValuesForPermissions(@RequestBody MultFieldValuesRequest multFieldValuesRequest) throws Exception {
return datasetDataManage.getFieldEnum(multFieldValuesRequest.getFieldIds());

View File

@ -77,4 +77,10 @@ public class DatasetTreeServer implements DatasetTreeApi {
public List<SqlVariableDetails> getSqlParams(List<Long> ids) throws Exception {
return datasetGroupManage.getSqlParams(ids);
}
@Override
public List<DatasetTableDTO> detailWithPerm(List<Long> ids) throws Exception {
return datasetGroupManage.getDetailWithPerm(ids);
}
}

View File

@ -302,6 +302,9 @@ public class ExcelUtils {
sdf.parse(value);
return "DATETIME";
} catch (Exception e1) {
if(value.length()> 19){
return "TEXT";
}
try {
Double d = Double.valueOf(value);
double eps = 1e-10;
@ -413,9 +416,6 @@ public class ExcelUtils {
}
List<String[]> data = new ArrayList<>(noModelDataListener.getData());
if (isPreview) {
if (data.size() > 100) {
data = data.subList(0, 100);
}
for (int i = 0; i < data.size(); i++) {
for (int j = 0; j < data.get(i).length; j++) {
if (j < fields.size()) {
@ -423,6 +423,9 @@ public class ExcelUtils {
}
}
}
if (data.size() > 100) {
data = data.subList(0, 100);
}
}
for (int i = 0; i < fields.size(); i++) {
@ -469,6 +472,9 @@ public class ExcelUtils {
}
}
}
if (data.size() > 100) {
data = data.subList(0, 100);
}
}
for (int i = 0; i < fields.size(); i++) {
if (StringUtils.isEmpty(fields.get(i).getFieldType())) {

View File

@ -87,6 +87,8 @@ public class SQLConstants {
public static final String WHERE_BETWEEN = "'%s' AND '%s'";
public static final String WHERE_VALUE_BETWEEN = "%s AND %s";
public static final String BRACKETS = "(%s)";
public static final String ROUND = "ROUND(%s,%s)";

View File

@ -67,6 +67,7 @@ public class ExtWhere2Str {
String cast = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT);
// 此处获取标准格式的日期
whereName = String.format(SQLConstants.FROM_UNIXTIME, cast, date_format);
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
}
if (field.getDeExtractType() == 1) {
// 此处获取标准格式的日期
@ -109,7 +110,7 @@ public class ExtWhere2Str {
if (request.getDatasetTableField().getDeExtractType() == 2
|| request.getDatasetTableField().getDeExtractType() == 3
|| request.getDatasetTableField().getDeExtractType() == 4) {
whereValue = String.format(SQLConstants.WHERE_BETWEEN, value.get(0), value.get(1));
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, value.get(0), value.get(1));
} else {
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
whereValue = String.format(SQLConstants.WHERE_BETWEEN, Long.parseLong(value.get(0)), Long.parseLong(value.get(1)));

View File

@ -18,7 +18,7 @@ public abstract class DeScheduleJob implements Job {
this.expression = jobDataMap.getString("expression");
this.taskId = jobDataMap.getLong("taskId");
this.updateType = jobDataMap.getString("updateType");
LogUtil.info(jobKey.getGroup() + " Running: " + datasetTableId);
LogUtil.info(jobKey.getName() + " Running: " + datasetTableId);
LogUtil.info("CronExpression: " + expression);
businessExecute(context);
}

View File

@ -1,5 +1,8 @@
package io.dataease.map.manage;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.api.map.dto.GeometryNodeCreator;
import io.dataease.api.map.vo.AreaNode;
import io.dataease.constant.StaticResourceConstants;
@ -29,6 +32,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static io.dataease.constant.CacheConstant.CommonCacheConstant.WORLD_MAP_CACHE;
@ -107,6 +111,13 @@ public class MapManage {
@CacheEvict(cacheNames = WORLD_MAP_CACHE, key = "'world_map'")
@Transactional
public void saveMapGeo(GeometryNodeCreator request, MultipartFile file) {
if (ObjectUtils.isEmpty(file) || file.isEmpty()) {
DEException.throwException("geometry file is require");
}
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
if (!StringUtils.equalsIgnoreCase("json", suffix)) {
DEException.throwException("仅支持json格式文件");
}
List<Area> areas = proxy().defaultArea();
String code = getBusiGeoCode(request.getCode());
@ -147,10 +158,30 @@ public class MapManage {
if (!StringUtils.startsWith(code, GEO_PREFIX)) {
DEException.throwException("内置Geometry禁止删除");
}
coreAreaCustomMapper.deleteById(code);
File file = buildGeoFile(code);
if (file.exists()) {
file.delete();
CoreAreaCustom coreAreaCustom = coreAreaCustomMapper.selectById(code);
if (ObjectUtils.isEmpty(coreAreaCustom)) {
DEException.throwException("Geometry code 不存在!");
}
List<String> codeResultList = new ArrayList<>();
codeResultList.add(code);
childTreeIdList(ListUtil.of(code), codeResultList);
coreAreaCustomMapper.deleteBatchIds(codeResultList);
codeResultList.forEach(id -> {
File file = buildGeoFile(id);
if (file.exists()) {
file.delete();
}
});
}
public void childTreeIdList(List<String> pidList, List<String> resultList) {
QueryWrapper<CoreAreaCustom> queryWrapper = new QueryWrapper<>();
queryWrapper.in("pid", pidList);
List<CoreAreaCustom> coreAreaCustoms = coreAreaCustomMapper.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(coreAreaCustoms)) {
List<String> codeList = coreAreaCustoms.stream().map(CoreAreaCustom::getId).toList();
resultList.addAll(codeList);
childTreeIdList(codeList, resultList);
}
}

View File

@ -96,6 +96,7 @@ public class MenuManage {
|| coreMenu.getId().equals(21L)
|| coreMenu.getPid().equals(21L)
|| coreMenu.getId().equals(25L)
|| coreMenu.getId().equals(26L);
|| coreMenu.getId().equals(26L)
|| coreMenu.getId().equals(35L);
}
}

View File

@ -22,12 +22,6 @@ spring:
port: 6379
password: 123456
database: 0
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
jackson:
parser:
allow-numeric-leading-zeros: true
@ -52,12 +46,21 @@ quartz:
dataease:
version: '@project.version@'
origin-list: localhost:8081,127.0.0.1:8081,https://de2.fit2cloud.com,http://localhost:8080
apisix-api:
domain: http://192.168.0.121:9180
key: edd1c9f034335f136f87ad84b625c8f1
# springdoc-openapi项目配置
springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
#operations-sorter: alpha
api-docs:
path: /v3/api-docs
# knife4j的增强配置不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
enable-swagger-models: false

View File

@ -14,64 +14,78 @@ CREATE TABLE `visualization_template` (
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
CREATE TABLE `visualization_template`
(
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '模板种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
);
-- ----------------------------
-- Table structure for visualization_template_category
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category`;
CREATE TABLE `visualization_template_category` (
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '模板种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
CREATE TABLE `visualization_template_category`
(
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '模板种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
-- ----------------------------
-- Table structure for visualization_template_category_map
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category_map`;
CREATE TABLE `visualization_template_category_map` (
`id` varchar(50) NOT NULL COMMENT '主键',
`category_id` varchar(255) DEFAULT NULL COMMENT '名称',
`template_id` varchar(255) DEFAULT NULL COMMENT '父级id',
PRIMARY KEY (`id`)
CREATE TABLE `visualization_template_category_map`
(
`id` varchar(50) NOT NULL COMMENT '主键',
`category_id` varchar(255) DEFAULT NULL COMMENT '名称',
`template_id` varchar(255) DEFAULT NULL COMMENT '父级id',
PRIMARY KEY (`id`)
);
-- ----------------------------
-- Table structure for visualization_template_extend_data
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_extend_data`;
CREATE TABLE `visualization_template_extend_data` (
`id` bigint NOT NULL,
`dv_id` bigint DEFAULT NULL,
`view_id` bigint DEFAULT NULL,
`view_details` longtext ,
`copy_from` varchar(255) DEFAULT NULL,
`copy_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
CREATE TABLE `visualization_template_extend_data`
(
`id` bigint NOT NULL,
`dv_id` bigint DEFAULT NULL,
`view_id` bigint DEFAULT NULL,
`view_details` longtext,
`copy_from` varchar(255) DEFAULT NULL,
`copy_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
BEGIN;
INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (30, 0, 1, 'toolbox', null, 7, 'icon_template', '/toolbox', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (31, 30, 2, 'template-setting', 'toolbox/template-setting', 1, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`,
ADD COLUMN `resource_name` varchar(255) NULL COMMENT '资源名称' AFTER `resource_id`;
ALTER TABLE core_opt_recent ADD `resource_name` varchar(255) NULL COMMENT '资源名称';
DROP TABLE IF EXISTS `core_area_custom`;
CREATE TABLE `core_area_custom`
@ -82,11 +96,11 @@ CREATE TABLE `core_area_custom`
PRIMARY KEY (`id`)
);
BEGIN;
INSERT INTO `core_sys_setting`
VALUES (1, 'basic.dsIntervalTime', '6', 'text', 2);
INSERT INTO `core_sys_setting`
VALUES (2, 'basic.dsExecuteTime', 'minute', 'text', 3);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (7, 'template.url', 'https://templates.dataease.cn', 'text', 0);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (8, 'template.accessKey', 'dataease', 'text', 1);
COMMIT;
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`)
VALUES (7, 'template.url', 'https://templates.dataease.cn', 'text', 0);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`)
VALUES (8, 'template.accessKey', 'dataease', 'text', 1);

View File

@ -3748,7 +3748,7 @@ CREATE TABLE QRTZ_JOB_DETAILS
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
);
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
@ -3827,9 +3827,7 @@ CREATE TABLE QRTZ_BLOB_TRIGGERS
PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
);
CREATE TABLE QRTZ_CALENDARS
(
@ -3896,9 +3894,7 @@ CREATE TABLE `visualization_background`
`base_url` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
);
INSERT INTO `visualization_background` (`id`, `name`, `classification`, `content`, `remark`, `sort`, `upload_time`,
`base_url`, `url`)
@ -3947,11 +3943,7 @@ CREATE TABLE `visualization_background_image`
`base_url` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
);
-- ----------------------------
-- Table structure for visualization_subject
@ -3959,7 +3951,7 @@ CREATE TABLE `visualization_background_image`
DROP TABLE IF EXISTS `visualization_subject`;
CREATE TABLE `visualization_subject`
(
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`id` varchar(50) NOT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '主题名称',
`type` varchar(255) DEFAULT NULL COMMENT '主题类型 system 系统主题self 自定义主题',
`details` longtext COMMENT '主题内容',
@ -3973,11 +3965,7 @@ CREATE TABLE `visualization_subject`
`delete_time` bigint DEFAULT NULL COMMENT '删除时间',
`delete_by` bigint DEFAULT NULL COMMENT '删除人',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
);
commit;
DROP TABLE IF EXISTS `core_dataset_table_sql_log`;
@ -3991,9 +3979,7 @@ CREATE TABLE `core_dataset_table_sql_log`
`sql` longtext NOT NULL COMMENT '详细信息',
`status` varchar(45) DEFAULT NULL COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE utf8mb4_0900_ai_ci;
);
INSERT INTO `visualization_subject` (`id`, `name`, `type`, `details`, `delete_flag`, `cover_url`, `create_num`,
@ -4024,9 +4010,7 @@ CREATE TABLE `core_store`
`resource_type` int NOT NULL COMMENT '资源类型',
`time` bigint NOT NULL COMMENT '收藏时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for xpack_share
@ -4044,9 +4028,7 @@ CREATE TABLE `xpack_share`
`oid` bigint NOT NULL COMMENT '组织ID',
`type` int NOT NULL COMMENT '业务类型',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for xpack_setting_authentication
@ -4061,25 +4043,8 @@ CREATE TABLE `xpack_setting_authentication`
`sync_time` bigint NOT NULL COMMENT '同步时间',
`relational_ids` varchar(255) DEFAULT NULL COMMENT '相关的ID',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
/*
Navicat Premium Data Transfer
Source Server : de2-qa-123.56.90.236
Source Server Type : MySQL
Source Server Version : 80100
Source Host : 123.56.90.236:3306
Source Schema : dataease
Target Server Type : MySQL
Target Server Version : 80100
File Encoding : 65001
Date: 22/09/2023 00:30:08
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
@ -4093,14 +4058,12 @@ CREATE TABLE `visualization_link_jump`
`id` bigint NOT NULL,
`source_dv_id` bigint DEFAULT NULL COMMENT '源仪表板ID',
`source_view_id` bigint DEFAULT NULL COMMENT '源视图ID',
`link_jump_info` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '跳转信息',
`link_jump_info` varchar(4000) DEFAULT NULL COMMENT '跳转信息',
`checked` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`copy_from` bigint DEFAULT NULL,
`copy_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for visualization_link_jump_info
@ -4110,19 +4073,17 @@ CREATE TABLE `visualization_link_jump_info`
(
`id` bigint NOT NULL,
`link_jump_id` bigint DEFAULT NULL COMMENT 'link jump ID',
`link_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '关联类型 inner 内部仪表板outer 外部链接',
`jump_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '跳转类型 _blank 新开页面 _self 当前窗口',
`link_type` varchar(255) DEFAULT NULL COMMENT '关联类型 inner 内部仪表板outer 外部链接',
`jump_type` varchar(255) DEFAULT NULL COMMENT '跳转类型 _blank 新开页面 _self 当前窗口',
`target_dv_id` bigint DEFAULT NULL COMMENT '关联仪表板ID',
`source_field_id` bigint DEFAULT NULL COMMENT '字段ID',
`content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '内容 linkType = outer时使用',
`content` varchar(4000) DEFAULT NULL COMMENT '内容 linkType = outer时使用',
`checked` tinyint(1) DEFAULT NULL COMMENT '是否可用',
`attach_params` tinyint(1) DEFAULT NULL COMMENT '是否附加点击参数',
`copy_from` bigint DEFAULT NULL,
`copy_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for visualization_link_jump_target_view_info
@ -4138,9 +4099,7 @@ CREATE TABLE `visualization_link_jump_target_view_info`
`copy_from` bigint DEFAULT NULL,
`copy_id` bigint DEFAULT NULL,
PRIMARY KEY (`target_id`) USING BTREE
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for visualization_linkage
@ -4160,9 +4119,7 @@ CREATE TABLE `visualization_linkage`
`copy_from` bigint DEFAULT NULL,
`copy_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
);
-- ----------------------------
-- Table structure for visualization_linkage_field
@ -4178,16 +4135,11 @@ CREATE TABLE `visualization_linkage_field`
`copy_from` bigint DEFAULT NULL,
`copy_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
SET FOREIGN_KEY_CHECKS = 1;
);
ALTER TABLE `core_datasource`
ADD COLUMN `update_by` bigint NULL COMMENT '变更人' AFTER `update_time`;
DROP TABLE IF EXISTS `core_ds_finish_page`;
CREATE TABLE `core_ds_finish_page`
(
@ -4205,9 +4157,7 @@ CREATE TABLE `core_opt_recent`
`opt_type` int DEFAULT NULL COMMENT '1 新建 2 修改',
`time` bigint NOT NULL COMMENT '收藏时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);
-- ----------------------------
-- Table structure for core_sys_setting
@ -4221,6 +4171,4 @@ CREATE TABLE `core_sys_setting`
`type` varchar(255) NOT NULL COMMENT '类型',
`sort` int NOT NULL DEFAULT '0' COMMENT '顺序',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci;
);

View File

@ -14,7 +14,7 @@ CREATE TABLE `visualization_template` (
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='模板表';
) COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_category
@ -32,7 +32,7 @@ CREATE TABLE `visualization_template_category` (
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='模板表';
) COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_category_map
@ -43,7 +43,7 @@ CREATE TABLE `visualization_template_category_map` (
`category_id` varchar(255) DEFAULT NULL COMMENT '名称',
`template_id` varchar(255) DEFAULT NULL COMMENT '父级id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='模板表';
) COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_extend_data
@ -57,7 +57,7 @@ CREATE TABLE `visualization_template_extend_data` (
`copy_from` varchar(255) DEFAULT NULL,
`copy_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
);
BEGIN;
INSERT INTO `core_menu`

View File

@ -10,26 +10,6 @@
<persistence directory="/opt/dataease2.0/cache" />
<!--<cache alias="AlertsConfig" uses-template="heap-cache"/>
<cache alias="Alerts" uses-template="alerts-template"/>
<cache-template name="heap-cache">
<resources>
<heap unit="entries">1</heap>
<offheap unit="MB">1</offheap>
<disk persistent="true" unit="MB">100</disk>
</resources>
</cache-template>
<cache-template name="alerts-template">
<resources>
<heap unit="entries">1</heap>
<offheap unit="MB">1</offheap>
<disk persistent="true" unit="MB">100</disk>
</resources>
</cache-template>-->
<cache-template name="common-cache">
<expiry>
<none/>
@ -138,14 +118,6 @@
<cache alias="core_menu_cache" uses-template="common-cache">
<key-type>java.lang.String</key-type>
<value-type>java.util.List</value-type>
<!--<expiry>
<none/>
</expiry>
<resources>
<heap unit="entries">20</heap>
<offheap unit="MB">2</offheap>
<disk unit="MB" persistent="true">5</disk>
</resources>-->
</cache>
</config>

View File

@ -21,6 +21,7 @@ export function pathResolve(dir: string) {
return resolve(root, '.', dir)
}
export default {
base: './',
plugins: [
Vue(),
VueJsx(),

View File

@ -2,18 +2,12 @@ export default {
server: {
proxy: {
'/api/f': {
// target: 'http://192.168.31.38:8100',
target: 'http://localhost:8100',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/f/, '')
},
// 使用 proxy 实例
'/api': {
// target: 'http://qa-de2.fit2cloud.com',
// target: 'http://192.168.31.74:8100',
// target: 'https://de2.fit2cloud.com',
// target: 'http://localhost:8100',
// target: 'http://192.168.0.121:9080',
target: 'http://localhost:8100',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, 'de2api')

View File

@ -15,6 +15,7 @@ export interface Field {
extField: number
checked: boolean
fieldShortName: string
desensitized: boolean
}
export interface ComponentInfo {

View File

@ -154,6 +154,11 @@ export const getDsDetails = async (data): Promise<DatasetDetail[]> => {
return res?.data
})
}
export const getDsDetailsWithPerm = async (data): Promise<DatasetDetail[]> => {
return request.post({ url: '/datasetTree/detailWithPerm', data }).then(res => {
return res?.data
})
}
export const getSqlParams = async (data): Promise<ParamsDetail[]> => {
return request.post({ url: '/datasetTree/getSqlParams', data }).then(res => {
return res?.data
@ -175,6 +180,10 @@ export const multFieldValuesForPermissions = (data = {}) => {
return request.post({ url: '/datasetField/multFieldValuesForPermissions', data })
}
export const listFieldsWithPermissions = (datasetId: number) => {
return request.get({ url: '/datasetField/listWithPermissions/' + datasetId })
}
export const saveRowPermission = (data = {}) => {
return request.post({ url: '/dataset/rowPermissions/save', data })
}

View File

@ -0,0 +1,6 @@
@font-face {
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
src: url('AlibabaPuHuiTi-3-55-RegularL3.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 880 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

View File

@ -1,4 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.59845 0 3.57025 0H14.4298C16.4015 0 18 1.34315 18 3V15C18 16.6569 16.4015 18 14.4298 18H3.57025C1.59845 18 0 16.6569 0 15V3Z" fill="#3370FF"/>
<path d="M0 3C0 1.34315 1.59845 0 3.57025 0H14.4298C16.4015 0 18 1.34315 18 3V15C18 16.6569 16.4015 18 14.4298 18H3.57025C1.59845 18 0 16.6569 0 15V3Z" fill="#00d6b9"/>
<path d="M13.25 4.5C13.3826 4.5 13.5098 4.55268 13.6036 4.64645C13.6973 4.74021 13.75 4.86739 13.75 5V11C13.75 11.1326 13.6973 11.2598 13.6036 11.3536C13.5098 11.4473 13.3826 11.5 13.25 11.5H10.0337L11.5822 12.8762L10.9177 13.6237L9 11.9187L7.08225 13.6237L6.41775 12.8762L7.966 11.5H4.75C4.61739 11.5 4.49021 11.4473 4.39645 11.3536C4.30268 11.2598 4.25 11.1326 4.25 11V5C4.25 4.86739 4.30268 4.74021 4.39645 4.64645C4.49021 4.55268 4.61739 4.5 4.75 4.5H13.25ZM12.75 5.5H5.25V10.5H12.75V5.5ZM10.7192 6.3965L11.4262 7.1035L9.05875 9.471L7.90425 8.31675L7.1035 9.11775L6.3965 8.4105L7.90425 6.90275L9.0585 8.057L10.7192 6.3965Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 915 B

After

Width:  |  Height:  |  Size: 915 B

View File

@ -1,6 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_181_24877)">
<path d="M0 4C0 1.79086 2.13127 0 4.76033 0H19.2397C21.8687 0 24 1.79086 24 4V20C24 22.2091 21.8687 24 19.2397 24H4.76033C2.13127 24 0 22.2091 0 20V4Z" fill="#3370FF"/>
<path d="M0 4C0 1.79086 2.13127 0 4.76033 0H19.2397C21.8687 0 24 1.79086 24 4V20C24 22.2091 21.8687 24 19.2397 24H4.76033C2.13127 24 0 22.2091 0 20V4Z" fill="#16c0ff"/>
<path d="M4.66669 9.09589C4.66669 8.83447 4.81949 8.59716 5.05749 8.48898L11.7242 5.45868C11.8994 5.37901 12.1006 5.37901 12.2759 5.45868L18.9426 8.48898C19.1806 8.59716 19.3334 8.83447 19.3334 9.0959V15.5879C19.3334 15.8404 19.1907 16.0713 18.9648 16.1842L12.2982 19.5175C12.1105 19.6114 11.8896 19.6114 11.7019 19.5175L5.03521 16.1842C4.80936 16.0713 4.66669 15.8404 4.66669 15.5879V9.09589ZM16.8119 8.98512L12 6.7979L7.16215 8.99693L11.9733 11.0694L16.8119 8.98512ZM12.6667 12.2225V17.8426L18 15.1759V9.9251L12.6667 12.2225ZM6.00002 9.9481V15.1759L11.3334 17.8426V12.2455L6.00002 9.9481Z" fill="white"/>
</g>
<defs>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -187,7 +187,7 @@ const resetCustomColor = () => {
.custom-title {
justify-content: space-between;
color: #646a73;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 12px;
font-style: normal;
font-weight: 400;

View File

@ -90,7 +90,7 @@ const handleCheckAllChange = (val: CheckboxValueType) => {
.title,
.ed-checkbox {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-weight: 400;
padding: 5px 0;

View File

@ -411,7 +411,6 @@ onMounted(() => {
>
<tabs-group themes="light" :dv-model="dvModel"></tabs-group>
</component-group>
<!-- <component-button :show-split-line="true" icon-name="dv-tab" title="Tab"></component-button>-->
<component-button-label
icon-name="icon_copy_filled"
title="复用"

View File

@ -57,7 +57,7 @@ defineExpose({
> :nth-child(1) {
color: var(--deTextSecondary, #1f2329);
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -71,7 +71,7 @@ defineExpose({
.item,
.more {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
white-space: nowrap;
font-size: 14px;
font-weight: 400;

View File

@ -1,8 +1,7 @@
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes'
import { ElSelect, ElPopover, ElOption, ElIcon } from 'element-plus-secondary'
import { computed, reactive, nextTick, ref } from 'vue'
import { Icon } from '@/components/icon-custom'
import { ElSelect, ElOption } from 'element-plus-secondary'
import { computed, reactive } from 'vue'
const props = defineProps({
optionList: propTypes.arrayOf(
@ -15,28 +14,19 @@ const props = defineProps({
})
const state = reactive({
currentStatus: [],
activeStatus: []
})
const emits = defineEmits(['filter-change'])
const elPopoverU = ref(null)
const more = ref(null)
const statusChange = (id: string | number) => {
state.activeStatus = state.activeStatus.filter(ele => ele.id !== id)
}
const selectStatus = ids => {
const [item] = ids
state.activeStatus.push(item)
state.currentStatus = []
nextTick(() => {
elPopoverU.value?.hide()
more.value?.click()
})
emits(
'filter-change',
ids.map(item => item.label)
)
}
const optionListNotSelect = computed(() => {
return props.optionList.filter(ele => !state.activeStatus.map(t => t.id).includes(ele.id))
return [...props.optionList]
})
const clear = () => {
state.activeStatus = []
@ -50,48 +40,22 @@ defineExpose({
<div class="filter">
<span>{{ title }}</span>
<div class="filter-item">
<span
v-for="ele in state.activeStatus"
:key="ele.id"
class="item active"
@click="statusChange(ele.id)"
>{{ $t(ele.name) }}</span
<el-select
:teleported="false"
style="width: 100%"
v-model="state.activeStatus"
value-key="id"
filterable
multiple
@change="selectStatus"
>
<slot v-if="!!optionListNotSelect.length">
<el-popover
:show-arrow="false"
ref="elPopoverU"
placement="bottom"
popper-class="filter-popper"
width="200"
trigger="click"
>
<el-select
:teleported="false"
style="width: 100%"
v-model="state.currentStatus"
value-key="id"
filterable
multiple
@change="selectStatus"
>
<el-option
v-for="item in optionListNotSelect"
:key="item.name"
:label="item.name"
:value="item"
/>
</el-select>
<template #reference>
<span ref="more" class="more">
<el-icon>
<Icon name="icon_add_outlined"> </Icon>
</el-icon>
更多
</span>
</template>
</el-popover>
</slot>
<el-option
v-for="item in optionListNotSelect"
:key="item.name"
:label="item.name"
:value="item"
/>
</el-select>
</div>
</div>
</template>
@ -102,7 +66,7 @@ defineExpose({
> :nth-child(1) {
color: var(--deTextSecondary, #1f2329);
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -113,45 +77,6 @@ defineExpose({
.filter-item {
flex: 1;
.item,
.more {
font-family: PingFang SC;
white-space: nowrap;
font-size: 14px;
font-weight: 400;
line-height: 24px;
margin-right: 12px;
text-align: center;
padding: 1px 6px;
background: var(--deTextPrimary5, #f5f6f7);
color: var(--deTextPrimary, #1f2329);
border-radius: 2px;
cursor: pointer;
display: inline-block;
margin-bottom: 12px;
}
.active,
.more:hover {
background: var(--primary10, rgba(51, 112, 255, 0.1));
color: var(--primaryselect, #0c296e);
}
.more {
white-space: nowrap;
display: inline-flex;
align-items: center;
i {
margin-right: 5px;
}
}
}
}
</style>
<style lang="less">
.filter-popper {
padding: 0 !important;
background: #fff !important;
}
</style>

View File

@ -100,7 +100,7 @@ defineExpose({
> :nth-child(1) {
color: var(--deTextSecondary, #1f2329);
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -114,7 +114,7 @@ defineExpose({
.item,
.more {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
white-space: nowrap;
font-size: 14px;
font-weight: 400;

View File

@ -1,8 +1,7 @@
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes'
import { ElTreeSelect, ElPopover, ElIcon } from 'element-plus-secondary'
import { computed, reactive, ref, watch } from 'vue'
import { Icon } from '@/components/icon-custom'
import { ElTreeSelect } from 'element-plus-secondary'
import { computed, reactive, ref } from 'vue'
const props = defineProps({
optionList: propTypes.arrayOf(
@ -21,18 +20,8 @@ const state = reactive({
activeStatus: []
})
const elPopoverU = ref(null)
const more = ref(null)
const filterTree = ref(null)
const statusChange = (value: string | number) => {
state.activeStatus = state.activeStatus.filter(ele => ele?.value !== value)
state.currentStatus = state.currentStatus.filter(val => val !== value)
emits(
'filter-change',
state.activeStatus.map(item => item.value)
)
}
const emits = defineEmits(['filter-change'])
const filterTree = ref()
const treeChange = () => {
const nodes = state.currentStatus.map(id => {
return filterTree.value?.getNode(id).data
@ -43,23 +32,12 @@ const treeChange = () => {
state.activeStatus.map(item => item.value)
)
}
watch(
() => state.currentStatus,
() => {
treeChange()
},
{ deep: true, immediate: true }
)
const optionListNotSelect = computed(() => {
return [...props.optionList]
})
const clear = () => {
state.activeStatus = []
state.currentStatus = []
}
const emits = defineEmits(['filter-change'])
defineExpose({
clear
})
@ -69,46 +47,21 @@ defineExpose({
<div class="filter">
<span>{{ title }}</span>
<div class="filter-item">
<span
v-for="ele in state.activeStatus"
:key="ele.value"
class="item active"
@click="statusChange(ele.value)"
>{{ $t(ele.label) }}</span
>
<slot v-if="!!optionListNotSelect.length">
<el-popover
:show-arrow="false"
ref="elPopoverU"
placement="bottom"
popper-class="filter-popper"
width="200"
trigger="click"
>
<el-tree-select
ref="filterTree"
node-key="value"
:teleported="false"
style="width: 100%"
v-model="state.currentStatus"
:data="optionListNotSelect"
:highlight-current="true"
multiple
:render-after-expand="false"
:placeholder="$t('common.please_select') + $t('user.role')"
show-checkbox
check-on-click-node
/>
<template #reference>
<span ref="more" class="more">
<el-icon>
<Icon name="icon_add_outlined"> </Icon>
</el-icon>
更多
</span>
</template>
</el-popover>
</slot>
<el-tree-select
node-key="value"
ref="filterTree"
:teleported="false"
style="width: 100%"
@change="treeChange"
v-model="state.currentStatus"
:data="optionListNotSelect"
:highlight-current="true"
multiple
:render-after-expand="false"
:placeholder="$t('common.please_select') + $t('user.role')"
show-checkbox
check-on-click-node
/>
</div>
</div>
</template>
@ -119,7 +72,7 @@ defineExpose({
> :nth-child(1) {
color: var(--deTextSecondary, #1f2329);
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -130,45 +83,6 @@ defineExpose({
.filter-item {
flex: 1;
.item,
.more {
font-family: PingFang SC;
white-space: nowrap;
font-size: 14px;
font-weight: 400;
line-height: 24px;
margin-right: 12px;
text-align: center;
padding: 1px 6px;
background: var(--deTextPrimary5, #f5f6f7);
color: var(--deTextPrimary, #1f2329);
border-radius: 2px;
cursor: pointer;
display: inline-block;
margin-bottom: 12px;
}
.active,
.more:hover {
background: var(--primary10, rgba(51, 112, 255, 0.1));
color: var(--primaryselect, #0c296e);
}
.more {
white-space: nowrap;
display: inline-flex;
align-items: center;
i {
margin-right: 5px;
}
}
}
}
</style>
<style lang="less">
.filter-popper {
padding: 0 !important;
background: #fff !important;
}
</style>

View File

@ -55,7 +55,7 @@ const getAssetsFile = {
color: var(--N600, #646a73);
text-align: center;
/* 正文-字号 14行高 22字重适中Regular用于列表Feed会话 */
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -71,7 +71,7 @@ watch(
display: flex;
align-items: center;
margin: 17px 0;
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-weight: 400;
.sum {

View File

@ -859,7 +859,7 @@ defineExpose({
color: var(--neutral-900, #1f2329);
/* 中文/桌面端/正文 14 22 Regular */
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -103,10 +103,6 @@ const downloadViewDetails = () => {
const chart = { ...viewInfo.value, chartExtRequest, data: viewDataInfo }
exportExcelDownload(chart)
}
//
// const htmlToImage = () => {
// downloadCanvas('img', viewContainer.value, viewInfo.value.title)
// }
const htmlToImage = () => {
toPng(viewContainer.value)

View File

@ -266,7 +266,7 @@ defineExpose({
<style lang="less">
.jump-linkage {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
.chart-dataset-name {

View File

@ -35,6 +35,10 @@ const cacheRequest = cb => {
}
export const configHandler = config => {
const desktop = wsCache.get('app.desktop')
if (desktop) {
return config
}
if (wsCache.get('user.token')) {
config.headers['X-DE-TOKEN'] = wsCache.get('user.token')
const expired = isExpired()

View File

@ -1,8 +1,10 @@
<script lang="ts" setup>
import eventBus from '@/utils/eventBus'
import { ElMessage } from 'element-plus-secondary'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import QueryConditionConfiguration from './QueryConditionConfiguration.vue'
import type { ComponentInfo } from '@/api/chart'
import { infoFormat } from './options'
import {
onBeforeUnmount,
reactive,
@ -15,7 +17,6 @@ import {
} from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from '@/hooks/web/useI18n'
import { guid } from '@/views/visualized/data/dataset/form/util.js'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { comInfo } from './com-info'
import { useEmitt } from '@/hooks/web/useEmitt'
@ -191,48 +192,6 @@ const dragover = () => {
// do
}
const infoFormat = (obj: ComponentInfo) => {
const { id, name, deType, type, datasetId } = obj
return {
id: guid(),
name,
showError: true,
timeGranularity: 'date',
timeGranularityMultiple: 'datetimerange',
field: {
id,
type,
name,
deType
},
timeType: 'fixed',
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
arbitraryTime: new Date(),
auto: false,
defaultValue: undefined,
selectValue: undefined,
optionValueSource: 0,
valueSource: [],
dataset: {
id: datasetId,
name: '',
fields: []
},
visible: true,
defaultValueCheck: false,
multiple: false,
displayType: '0',
checkedFields: [],
parameters: [],
parametersCheck: false,
parametersList: [],
checkedFieldsMap: {}
}
}
const drop = e => {
const componentInfo: ComponentInfo = JSON.parse(e.dataTransfer.getData('dimension') || '{}')
if (!componentInfo.id) return
@ -260,34 +219,9 @@ const editeQueryConfig = (queryId: string) => {
queryConfig.value.setCondition(queryId)
}
const addQueryCriteria = () => {
const componentInfo: ComponentInfo = {
id: '',
name: '未命名',
deType: 0,
type: 'VARCHAR',
datasetId: ''
}
list.value.push(infoFormat(componentInfo))
element.value.propValue = [...list.value]
snapshotStore.recordSnapshotCache()
editeQueryConfig(list.value[list.value.length - 1].id)
}
const addQueryCriteriaConfig = () => {
const componentInfo: ComponentInfo = {
id: '',
name: '未命名',
deType: 0,
type: 'VARCHAR',
datasetId: ''
}
return infoFormat(componentInfo)
}
const editQueryCriteria = () => {
if (!list.value.length) {
addQueryCriteria()
addCriteriaConfigOut()
return
}
editeQueryConfig(list.value[0].id)
@ -333,12 +267,21 @@ const listVisible = computed(() => {
return list.value.filter(itx => itx.visible)
})
const addCriteriaConfig = () => {
queryConfig.value.setConditionInit(queryConfig.value.addCriteriaConfig())
}
const queryData = () => {
let requiredName = ''
const emitterList = (element.value.propValue || []).reduce((pre, next) => {
if (next.required) {
if (!next.defaultValueCheck) {
requiredName = next.name
}
if (
(Array.isArray(next.selectValue) && !next.selectValue.length) ||
(next.selectValue !== 0 && !next.selectValue)
) {
requiredName = next.name
}
}
const keyList = Object.entries(next.checkedFieldsMap)
.filter(ele => next.checkedFields.includes(ele[0]))
.filter(ele => !!ele[1])
@ -346,6 +289,10 @@ const queryData = () => {
pre = [...new Set([...keyList, ...pre])]
return pre
}, [])
if (!!requiredName) {
ElMessage.error(`${requiredName}】查询条件是必填项,请设置选项值后,再进行查询!`)
return
}
if (!emitterList.length) return
emitterList.forEach(ele => {
@ -390,7 +337,7 @@ const opacityStyle = computed(() => {
<div v-if="!listVisible.length" class="no-list-label flex-align-center">
<div class="container flex-align-center">
将右侧的字段拖拽到这里 点击
<el-button :disabled="showPosition === 'preview'" @click="addCriteriaConfig" text>
<el-button :disabled="showPosition === 'preview'" @click="addCriteriaConfigOut" text>
添加查询条件
</el-button>
</div>
@ -404,6 +351,7 @@ const opacityStyle = computed(() => {
<el-tooltip effect="dark" :content="ele.name" placement="top">
{{ ele.name }}
</el-tooltip>
<span v-if="ele.required" class="required">*</span>
</div>
</div>
<div class="label-wrapper-tooltip" v-if="showPosition !== 'preview'">
@ -445,7 +393,6 @@ const opacityStyle = computed(() => {
</div>
<Teleport to="body">
<QueryConditionConfiguration
:add-query-criteria-config="addQueryCriteriaConfig"
:query-element="element"
ref="queryConfig"
></QueryConditionConfiguration>
@ -471,7 +418,7 @@ const opacityStyle = computed(() => {
justify-content: center;
color: #646a73;
text-align: center;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 16px;
font-style: normal;
font-weight: 400;
@ -487,7 +434,7 @@ const opacityStyle = computed(() => {
.title {
color: #1f2329;
font-feature-settings: 'clig' off, 'liga' off;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 500;
@ -538,6 +485,7 @@ const opacityStyle = computed(() => {
overflow: hidden;
}
.label-wrapper-text {
position: relative;
cursor: pointer;
flex: 0 1 auto;
max-width: 100%;
@ -545,11 +493,18 @@ const opacityStyle = computed(() => {
text-overflow: ellipsis;
white-space: nowrap;
color: #1f2329;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
.required {
font-size: 14px;
color: #f54a45;
margin-left: 3px;
line-height: 22px;
}
}
.label-wrapper-tooltip {
align-items: center;

View File

@ -0,0 +1,151 @@
<script lang="ts" setup>
import { toRefs, PropType, ref, onBeforeMount, watch, computed } from 'vue'
import { Calendar } from '@element-plus/icons-vue'
import { type DatePickType } from 'element-plus-secondary'
import { getCustomTime } from './time-format'
interface SelectConfig {
timeType: string
defaultValue: [Date, Date]
selectValue: [Date, Date]
defaultValueCheck: boolean
id: string
timeNum: number
relativeToCurrentType: string
around: string
arbitraryTime: Date
timeGranularity: DatePickType
timeNumRange: number
relativeToCurrentTypeRange: string
aroundRange: string
arbitraryTimeRange: Date
}
const props = defineProps({
config: {
type: Object as PropType<SelectConfig>,
default: () => {
return {
defaultValue: [],
selectValue: [],
timeType: 'fixed',
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
arbitraryTime: new Date(),
defaultValueCheck: false,
timeGranularity: 'date',
timeNumRange: 0,
relativeToCurrentTypeRange: 'year',
aroundRange: 'f',
arbitraryTimeRange: new Date()
}
}
}
})
const selectValue = ref<[Date, Date]>([new Date(), new Date()])
const { config } = toRefs(props)
const timeConfig = computed(() => {
const {
timeNum,
relativeToCurrentType,
around,
defaultValueCheck,
arbitraryTime,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
arbitraryTimeRange
} = config.value
return {
timeNum,
relativeToCurrentType,
around,
defaultValueCheck,
arbitraryTime,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
arbitraryTimeRange
}
})
watch(
() => timeConfig.value,
() => {
init()
},
{
deep: true
}
)
watch(
() => selectValue.value,
val => {
config.value.defaultValue = val
config.value.selectValue = val
}
)
watch(
() => config.value.id,
() => {
init()
}
)
const init = () => {
const {
timeNum,
relativeToCurrentType,
around,
defaultValueCheck,
arbitraryTime,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
arbitraryTimeRange
} = timeConfig.value
if (!defaultValueCheck) {
selectValue.value = [new Date(), new Date()]
return
}
const startTime = getCustomTime(
timeNum,
relativeToCurrentType,
timeGranularity,
around,
arbitraryTime
)
const endTime = getCustomTime(
timeNumRange,
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
arbitraryTimeRange
)
selectValue.value = [startTime, endTime]
}
onBeforeMount(() => {
init()
})
</script>
<template>
<el-date-picker
disabled
v-model="selectValue"
type="datetimerange"
:prefix-icon="Calendar"
:range-separator="$t('cron.to')"
:start-placeholder="$t('datasource.start_time')"
:end-placeholder="$t('datasource.end_time')"
/>
</template>

View File

@ -1,18 +1,21 @@
<script lang="ts" setup>
import { ref, reactive, nextTick, computed, shallowRef, toRefs, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { addQueryCriteriaConfig } from './options'
import { getCustomTime } from './time-format'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { useI18n } from '@/hooks/web/useI18n'
import { fieldType } from '@/utils/attr'
import { ElMessage } from 'element-plus-secondary'
import type { DatasetDetail } from '@/api/dataset'
import { getDsDetails, getSqlParams } from '@/api/dataset'
import { getDsDetailsWithPerm, getSqlParams, listFieldsWithPermissions } from '@/api/dataset'
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
import { cloneDeep } from 'lodash-es'
import Select from './Select.vue'
import Time from './Time.vue'
import DynamicTime from './DynamicTime.vue'
import DynamicTimeRange from './DynamicTimeRange.vue'
import { getDatasetTree } from '@/api/dataset'
import { Tree } from '@/views/visualized/data/dataset/form/CreatDsGroup.vue'
import draggable from 'vuedraggable'
@ -30,10 +33,6 @@ interface DatasetField {
}
const props = defineProps({
addQueryCriteriaConfig: {
type: Function,
default: () => ({})
},
queryElement: {
type: Object,
default() {
@ -109,6 +108,10 @@ const parametersFilter = computed(() => {
if (curComponent.value.displayType === '2') {
return [2, 3].includes(ele.deType)
}
if (curComponent.value.displayType === '7') {
return [1, 7].includes(ele.deType)
}
return ele.deType === +curComponent.value.displayType
})
})
@ -258,7 +261,59 @@ const validate = () => {
return true
}
if ([1, 7].includes(+ele.displayType)) {
if (ele.required) {
if (!ele.defaultValueCheck) {
ElMessage.error('查询条件为必填项,默认值不能为空')
return true
}
if (
(Array.isArray(ele.defaultValue) && !ele.defaultValue.length) ||
(ele.defaultValue !== 0 && !ele.defaultValue)
) {
ElMessage.error('查询条件为必填项,默认值不能为空')
return true
}
}
if (+ele.displayType === 7) {
if (!ele.defaultValueCheck) {
return false
}
const {
timeNum,
relativeToCurrentType,
around,
arbitraryTime,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
arbitraryTimeRange
} = ele
const startTime = getCustomTime(
timeNum,
relativeToCurrentType,
timeGranularity,
around,
arbitraryTime
)
const endTime = getCustomTime(
timeNumRange,
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
arbitraryTimeRange
)
if (+startTime > +endTime) {
ElMessage.error('结束时间必须大于开始时间!')
return true
}
return false
}
if ([1].includes(+ele.displayType)) {
return false
}
@ -335,8 +390,10 @@ const confirmValueSource = () => {
const filterTypeCom = computed(() => {
const { displayType, timeType = 'fixed' } = curComponent.value
return ['1', '7'].includes(displayType)
? timeType === 'dynamic' && displayType === '1'
? DynamicTime
? timeType === 'dynamic'
? displayType === '1'
? DynamicTime
: DynamicTimeRange
: Time
: Select
})
@ -346,10 +403,6 @@ const setCondition = (queryId: string) => {
init(queryId)
}
const setConditionInit = (queryId: string) => {
init(queryId)
}
const setConditionOut = () => {
conditions.value = cloneDeep(props.queryElement.propValue) || []
addQueryCriteria()
@ -388,15 +441,10 @@ const init = (queryId: string) => {
return { ...datasetMap[ele.tableId], componentId: ele.id }
})
.filter(ele => !!ele)
return
}
getDsDetails([
...new Set(
datasetFieldList.value
.map(ele => ele.tableId)
.filter(ele => !datasetMapKeyList.includes(ele) && ele)
)
])
const params = [...new Set(datasetFieldList.value.map(ele => ele.tableId).filter(ele => !!ele))]
if (!params.length) return
getDsDetailsWithPerm(params)
.then(res => {
res
.filter(ele => !!ele)
@ -426,11 +474,18 @@ const weightlessness = () => {
const parameterCompletion = () => {
const attributes = {
timeType: 'fixed',
required: false,
parametersStart: null,
parametersEnd: null,
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
arbitraryTime: new Date()
arbitraryTime: new Date(),
timeNumRange: 0,
relativeToCurrentTypeRange: 'year',
aroundRange: 'f',
arbitraryTimeRange: new Date()
}
Object.entries(attributes).forEach(([key, val]) => {
!curComponent.value[key] && (curComponent.value[key] = val)
@ -443,7 +498,7 @@ const handleCondition = item => {
curComponent.value = conditions.value.find(ele => ele.id === item.id)
multiple.value = curComponent.value.multiple
if (!curComponent.value.dataset.fields.length) {
if (!curComponent.value.dataset.fields.length && curComponent.value.dataset.id) {
getOptions(curComponent.value.dataset.id, curComponent.value)
}
datasetFieldList.value.forEach(ele => {
@ -473,12 +528,8 @@ const handleCondition = item => {
}
const getOptions = (id, component) => {
getDsDetails([id]).then(res => {
res.forEach(ele => {
if (!ele) return
const { dimensionList, quotaList } = ele.fields
component.dataset.fields = [...dimensionList, ...quotaList]
})
listFieldsWithPermissions(id).then(res => {
component.dataset.fields = res.data
})
}
@ -579,7 +630,7 @@ const relativeToCurrentList = computed(() => {
})
const dynamicTime = computed(() => {
return curComponent.value.timeType === 'dynamic' && curComponent.value.displayType === '1'
return curComponent.value.timeType === 'dynamic'
})
const relativeToCurrentTypeList = computed(() => {
@ -686,7 +737,7 @@ const renameInputBlur = () => {
}
const addQueryCriteria = () => {
conditions.value.push(props.addQueryCriteriaConfig())
conditions.value.push(addQueryCriteriaConfig())
}
const addCriteriaConfig = () => {
@ -696,7 +747,6 @@ const addCriteriaConfig = () => {
defineExpose({
setCondition,
setConditionInit,
addCriteriaConfig,
setConditionOut
})
@ -845,8 +895,12 @@ defineExpose({
:key="ele.id"
:label="ele.name"
:value="ele.id"
:disabled="ele.desensitized"
>
<div class="flex-align-center icon">
<div
class="flex-align-center icon"
:title="ele.desensitized ? '脱敏字段,不能被设置为查询条件' : ''"
>
<el-icon>
<Icon
:name="`field_${fieldType[ele.deType]}`"
@ -865,7 +919,14 @@ defineExpose({
</div>
<div class="condition-configuration">
<div class="mask condition" v-if="curComponent.auto"></div>
<div class="title">查询条件配置</div>
<div class="title flex-align-center">
查询条件配置
<el-checkbox
:disabled="curComponent.auto"
v-model="curComponent.required"
label="必填项"
/>
</div>
<div v-show="showConfiguration && !showTypeError" class="configuration-list">
<div class="list-item">
<div class="label">展示类型</div>
@ -995,8 +1056,12 @@ defineExpose({
:key="ele.id"
:label="ele.name"
:value="ele.id"
:disabled="ele.desensitized"
>
<div class="flex-align-center icon">
<div
class="flex-align-center icon"
:title="ele.desensitized ? '脱敏字段,不能被设置为查询条件' : ''"
>
<el-icon>
<Icon
:name="`field_${fieldType[ele.deType]}`"
@ -1088,27 +1153,73 @@ defineExpose({
<div class="label">
<el-checkbox v-model="curComponent.parametersCheck" label="绑定参数" />
</div>
<div v-if="curComponent.parametersCheck" class="parameters">
<el-select
popper-class="dataset-parameters"
value-key="id"
multiple
v-model="curComponent.parameters"
clearable
>
<el-option
v-for="item in parametersFilter"
:key="item.id"
:label="item.variableName"
:value="item"
<template v-if="curComponent.parametersCheck">
<div v-if="curComponent.displayType !== '7'" class="parameters">
<el-select
popper-class="dataset-parameters"
value-key="id"
multiple
v-model="curComponent.parameters"
clearable
>
<div class="variable-name ellipsis">{{ item.variableName }}</div>
<el-tooltip effect="dark" :content="item.datasetFullName" placement="top">
<div class="dataset-full-name ellipsis">{{ item.datasetFullName }}</div>
</el-tooltip>
</el-option>
</el-select>
</div>
<el-option
v-for="item in parametersFilter"
:key="item.id"
:label="item.variableName"
:value="item"
>
<div class="variable-name ellipsis">{{ item.variableName }}</div>
<el-tooltip effect="dark" :content="item.datasetFullName" placement="top">
<div class="dataset-full-name ellipsis">{{ item.datasetFullName }}</div>
</el-tooltip>
</el-option>
</el-select>
</div>
<div v-else class="parameters-range">
<div class="range-title">开始时间</div>
<div class="range-title">结束时间</div>
<div class="params-start">
<el-select
popper-class="dataset-parameters"
value-key="id"
v-model="curComponent.parametersStart"
clearable
>
<el-option
v-for="item in parametersFilter"
:key="item.id"
:label="item.variableName"
:value="item"
>
<div class="variable-name ellipsis">{{ item.variableName }}</div>
<el-tooltip effect="dark" :content="item.datasetFullName" placement="top">
<div class="dataset-full-name ellipsis">{{ item.datasetFullName }}</div>
</el-tooltip>
</el-option>
</el-select>
</div>
<div class="params-end">
<el-select
popper-class="dataset-parameters"
value-key="id"
v-model="curComponent.parametersEnd"
clearable
>
<el-option
v-for="item in parametersFilter"
:key="item.id"
:label="item.variableName"
:value="item"
>
<div class="variable-name ellipsis">{{ item.variableName }}</div>
<el-tooltip effect="dark" :content="item.datasetFullName" placement="top">
<div class="dataset-full-name ellipsis">{{ item.datasetFullName }}</div>
</el-tooltip>
</el-option>
</el-select>
</div>
</div>
</template>
</div>
<div class="list-item">
<div class="label">
@ -1116,7 +1227,7 @@ defineExpose({
</div>
<div
class="setting-content"
v-if="curComponent.defaultValueCheck && curComponent.displayType === '1'"
v-if="curComponent.defaultValueCheck && ['1', '7'].includes(curComponent.displayType)"
>
<div class="setting">
<el-radio-group v-model="curComponent.timeType">
@ -1124,7 +1235,7 @@ defineExpose({
<el-radio label="dynamic">动态时间</el-radio>
</el-radio-group>
</div>
<template v-if="dynamicTime">
<template v-if="dynamicTime && curComponent.displayType === '1'">
<div class="setting">
<div class="setting-label">相对当前</div>
<div class="setting-value select">
@ -1171,6 +1282,62 @@ defineExpose({
</div>
</div>
</template>
<template v-else-if="dynamicTime && curComponent.displayType === '7'">
<div class="setting">
<div class="setting-label">开始时间</div>
<div class="setting-input with-date range">
<el-input-number
v-model="curComponent.timeNum"
:min="0"
controls-position="right"
/>
<el-select v-model="curComponent.relativeToCurrentType">
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="curComponent.around">
<el-option
v-for="item in aroundList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-time-picker v-model="curComponent.arbitraryTime" />
</div>
</div>
<div class="setting">
<div class="setting-label">结束时间</div>
<div class="setting-input with-date range">
<el-input-number
v-model="curComponent.timeNumRange"
:min="0"
controls-position="right"
/>
<el-select v-model="curComponent.relativeToCurrentTypeRange">
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="curComponent.aroundRange">
<el-option
v-for="item in aroundList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-time-picker v-model="curComponent.arbitraryTimeRange" />
</div>
</div>
</template>
</div>
<div
v-if="curComponent.defaultValueCheck"
@ -1208,7 +1375,7 @@ defineExpose({
<style lang="less">
.dataset-parameters {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
.ed-select-dropdown__item {
@ -1240,7 +1407,7 @@ defineExpose({
}
.container {
font-size: 14px;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
width: 1152px;
height: 454px;
border-radius: 4px;
@ -1261,7 +1428,7 @@ defineExpose({
display: flex;
align-items: center;
justify-content: space-between;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 500;
@ -1309,7 +1476,6 @@ defineExpose({
}
.chart-field {
border-right: 1px solid #dee0e3;
height: calc(100% - 16px);
padding: 0 16px 16px 16px;
width: 474px;
@ -1329,7 +1495,7 @@ defineExpose({
}
.title {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 500;
@ -1381,6 +1547,7 @@ defineExpose({
.condition-configuration {
padding: 16px;
border-left: 1px solid #dee0e3;
width: 467px;
position: relative;
.mask {
@ -1392,7 +1559,7 @@ defineExpose({
color: #646a73;
height: 16px;
padding: 0px 4px;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 10px;
font-style: normal;
font-weight: 500;
@ -1401,9 +1568,20 @@ defineExpose({
background: rgba(31, 35, 41, 0.1);
margin-left: 8px;
}
.flex-align-center {
position: sticky;
top: 0;
justify-content: space-between;
background: #fff;
z-index: 5;
.ed-checkbox {
height: 20px;
}
}
.title {
margin-bottom: 16px;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 500;
@ -1449,6 +1627,7 @@ defineExpose({
.parameters {
margin-left: auto;
margin-top: 8px;
.w100 {
width: 100%;
@ -1466,8 +1645,38 @@ defineExpose({
}
}
}
.parameters-range {
width: 100%;
padding-left: 24px;
display: flex;
flex-wrap: wrap;
.range-title,
.params-start,
.params-end {
width: 50%;
}
.params-start,
.params-end {
margin-top: 8px;
.ed-select {
width: 100%;
}
}
.params-end {
padding-left: 4px;
}
.params-start {
padding-right: 4px;
}
}
.setting {
&.setting {
margin-top: 8px;
}
&.parameters {
width: 100%;
padding-left: 24px;
@ -1498,6 +1707,9 @@ defineExpose({
padding-left: 86px;
justify-content: flex-end;
align-items: center;
&.range {
padding-left: 0px;
}
& > div + div {
margin-left: 8px;
}

View File

@ -182,7 +182,7 @@ watch(
watch(
() => config.value.valueSource,
() => {
debounceOptions(2)
config.value.optionValueSource === 2 && debounceOptions(2)
}
)

View File

@ -0,0 +1,64 @@
import type { ComponentInfo } from '@/api/chart'
import { guid } from '@/views/visualized/data/dataset/form/util.js'
const infoFormat = (obj: ComponentInfo) => {
const { id, name, deType, type, datasetId } = obj
return {
id: guid(),
name,
showError: true,
timeGranularity: 'date',
timeGranularityMultiple: 'datetimerange',
field: {
id,
type,
name,
deType
},
timeType: 'fixed',
relativeToCurrent: 'custom',
required: false,
timeNum: 0,
relativeToCurrentType: 'year',
around: 'f',
parametersStart: null,
parametersEnd: null,
arbitraryTime: new Date(),
timeNumRange: 0,
relativeToCurrentTypeRange: 'year',
aroundRange: 'f',
arbitraryTimeRange: new Date(),
auto: false,
defaultValue: undefined,
selectValue: undefined,
optionValueSource: 0,
valueSource: [],
dataset: {
id: datasetId,
name: '',
fields: []
},
visible: true,
defaultValueCheck: false,
multiple: false,
displayType: '0',
checkedFields: [],
parameters: [],
parametersCheck: false,
parametersList: [],
checkedFieldsMap: {}
}
}
const addQueryCriteriaConfig = () => {
const componentInfo: ComponentInfo = {
id: '',
name: '未命名',
deType: 0,
type: 'VARCHAR',
datasetId: ''
}
return infoFormat(componentInfo)
}
export { infoFormat, addQueryCriteriaConfig }

View File

@ -50,7 +50,7 @@ function getCustomTime(
timeType: string,
timeGranularity: string,
around: string,
arbitraryTime?: string
arbitraryTime?: Date
) {
const date = new Date()
const num = around === 'f' ? -timeNum : timeNum
@ -80,7 +80,7 @@ function getCustomTime(
if (!!arbitraryTime) {
const time = new Date(arbitraryTime)
time.setFullYear(resultYear)
time.setMonth(resultMonth)
time.setMonth(resultMonth - 1)
time.setDate(resultDate)
return time
}

View File

@ -1,6 +1,6 @@
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { getDynamicRange } from '@/custom-component/v-query/time-format'
import { getDynamicRange, getCustomTime } from '@/custom-component/v-query/time-format'
const dvMainStore = dvMainStoreWithOut()
const { componentData } = storeToRefs(dvMainStore)
@ -90,6 +90,8 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
let selectValue = ''
const {
selectValue: value,
parametersStart,
parametersEnd,
defaultValueCheck,
timeType = 'fixed',
defaultValue,
@ -100,10 +102,43 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
displayType,
multiple
} = item
if (timeType === 'dynamic' && +displayType === 1 && firstLoad && !value?.length) {
selectValue = getDynamicRange(item)
item.defaultValue = new Date(selectValue[0])
item.selectValue = new Date(selectValue[0])
if (timeType === 'dynamic' && [1, 7].includes(+displayType) && firstLoad) {
if (+displayType === 1) {
selectValue = getDynamicRange(item)
item.defaultValue = new Date(selectValue[0])
item.selectValue = new Date(selectValue[0])
} else {
const {
timeNum,
relativeToCurrentType,
around,
arbitraryTime,
timeGranularity,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
arbitraryTimeRange
} = item
const startTime = getCustomTime(
timeNum,
relativeToCurrentType,
timeGranularity,
around,
arbitraryTime
)
const endTime = getCustomTime(
timeNumRange,
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
arbitraryTimeRange
)
item.defaultValue = [startTime, endTime]
item.selectValue = [startTime, endTime]
}
} else {
selectValue = getValueByDefaultValueCheckOrFirstLoad(
defaultValueCheck,
@ -123,7 +158,16 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
fieldId: item.checkedFieldsMap[curComponentId],
operator: [1, 7].includes(+displayType) ? 'between' : multiple ? 'in' : 'eq',
value: values,
parameters: parametersCheck ? parameters : [],
parameters: parametersCheck
? +displayType === 7
? [
parametersStart,
parametersEnd?.id
? { ...parametersEnd, id: `${parametersEnd.id}_START_END_SPLIT` }
: parametersEnd
]
: parameters
: [],
isTree
})
}

View File

@ -10,6 +10,8 @@ import { useEmitt } from '@/hooks/web/useEmitt'
import AboutPage from '@/views/about/index.vue'
import LangSelector from './LangSelector.vue'
import router from '@/router'
import { useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
const userStore = useUserStoreWithOut()
const { t } = useI18n()
@ -30,6 +32,16 @@ const linkLoaded = items => {
items.forEach(item => linkList.value.push(item))
linkList.value.sort(compare('id'))
}
const xpackLinkLoaded = items => {
let len = linkList.value.length
while (len--) {
if (linkList.value[len]?.id === 2 && linkList.value[len]?.link === '/modify-pwd/index') {
linkList.value.splice(len, 1)
}
}
items.forEach(item => linkList.value.push(item))
linkList.value.sort(compare('id'))
}
const compare = (property: string) => {
return (a, b) => a[property] - b[property]
@ -68,6 +80,10 @@ const openPopover = () => {
if (uid.value === '1') {
linkLoaded([{ id: 4, link: '/sys-setting/parameter', label: t('commons.system_setting') }])
const desktop = wsCache.get('app.desktop')
if (!desktop) {
linkLoaded([{ id: 2, link: '/modify-pwd/index', label: t('user.change_password') }])
}
}
</script>
@ -138,7 +154,7 @@ if (uid.value === '1') {
</el-popover>
<AboutPage />
<XpackComponent jsname="dWNlbnRlci1oYW5kbGVy" @loaded="linkLoaded" />
<XpackComponent jsname="dWNlbnRlci1oYW5kbGVy" @loaded="xpackLinkLoaded" />
</template>
<style lang="less">

View File

@ -32,7 +32,7 @@ const backToMain = () => {
<style lang="less" scoped>
.system-header {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
.logo {
width: 134px;

View File

@ -28,7 +28,7 @@ const backToMain = () => {
<style lang="less" scoped>
.system-header {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
.logo {
width: 134px;

View File

@ -1353,8 +1353,8 @@ export default {
export_filter: '筛选条件',
pls_input_filename: '请输入文件名称',
calc_tips: {
tip1: '表达式语法请遵循该数据源对应的数据库语法',
tip2: '数据集中不支持聚合运算',
tip1: '表达式语法请遵循calcite语法',
tip2: '聚合运算仅能在图表中生效',
tip3: '引用字段以 "[" 开始 "]" 结束',
tip4: '请勿修改引用内容否则将引用失败',
tip5: '若输入与引用字段相同格式的内容将被当作引用字段处理',

View File

@ -1,4 +1,5 @@
import { createApp } from 'vue'
import '../../assets/font/index.css'
import '@/style/index.less'
import '@/plugins/svg-icon'
import 'normalize.css/normalize.css'

View File

@ -8,6 +8,10 @@ const DashboardEditor = defineAsyncComponent(() => import('@/views/dashboard/ind
const Dashboard = defineAsyncComponent(() => import('./DashboardPreview.vue'))
const ViewWrapper = defineAsyncComponent(() => import('./ViewWrapper.vue'))
const Dataset = defineAsyncComponent(() => import('@/views/visualized/data/dataset/index.vue'))
const Datasource = defineAsyncComponent(
() => import('@/views/visualized/data/datasource/index.vue')
)
const props = defineProps({
componentName: propTypes.string.def('DashboardEditor')
})
@ -17,7 +21,9 @@ const componentMap = {
DashboardEditor,
VisualizationEditor,
ViewWrapper,
Dashboard
Dashboard,
Dataset,
Datasource
}
currentComponent.value = componentMap[props.componentName]

View File

@ -96,6 +96,22 @@ export const routes: AppRouteRecordRaw[] = [
hidden: true,
meta: {},
component: () => import('@/custom-component/rich-text/DeRichTextView.vue')
},
{
path: '/modify-pwd',
name: 'modify-pwd',
hidden: true,
meta: {},
component: () => import('@/layout/index.vue'),
children: [
{
path: 'index',
name: 'mpi',
hidden: true,
component: () => import('@/views/system/modify-pwd/index.vue'),
meta: { hidden: true }
}
]
}
]

View File

@ -85,6 +85,9 @@ export const userStore = defineStore('user', {
this.oid = oid
},
setLanguage(language: string) {
if (!language || language === 'zh_CN') {
language = 'zh-CN'
}
wsCache.set('user.language', language)
this.language = language
locale.setLang(language)

View File

@ -1,12 +1,12 @@
:root {
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, \5fae\8f6f\96c5\9ed1, Arial, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Helvetica Neue, Helvetica, '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei,
\5fae\8f6f\96c5\9ed1, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
font-synthesis: none;
// text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
@ -54,7 +54,6 @@ body {
white-space: nowrap;
}
.list-item_primary {
height: 40px;
border-radius: 4px;
@ -70,7 +69,7 @@ body {
.label {
width: 85%;
font-size: 14px;
.ellipsis
.ellipsis;
}
&:not(.active):hover {
@ -79,7 +78,7 @@ body {
&.active {
background: rgba(51, 112, 255, 0.1);
color: #3370FF;
color: #3370ff;
}
}
@ -101,7 +100,7 @@ body {
}
.title-form_primary {
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 500;
font-size: 14px;
@ -130,28 +129,28 @@ body {
background-color: #f5f6f7 !important;
.ed-table-v2__header-cell {
background-color: transparent
background-color: transparent;
}
}
.field-icon-text {
color: #3370FF;
color: #3370ff;
}
.field-icon-time {
color: #3370FF;
color: #3370ff;
}
.field-icon-value {
color: #04B49C;
color: #04b49c;
}
.field-icon-location {
color: #3370FF;
color: #3370ff;
}
.field-icon-red {
color: #F54A45;
color: #f54a45;
}
.field-icon-sort {
@ -161,24 +160,22 @@ body {
}
.field-icon-dimension {
color: #3370FF;
color: #3370ff;
}
.field-icon-quota {
color: #04B49C;
color: #04b49c;
}
.hover-icon {
cursor: pointer;
height: 24px !important;
width: 24px !important;
font-size: 16px !important;
border-radius: 4px;
color: #646A73 !important;
color: #646a73 !important;
&[aria-expanded="true"] {
&[aria-expanded='true'] {
background: rgba(31, 35, 41, 0.1);
}
@ -198,25 +195,24 @@ body {
}
.hover-icon-in-table {
color: #3370FF !important;
&[aria-expanded="true"] {
background: rgba(51,112,255,.1);
color: #3370ff !important;
&[aria-expanded='true'] {
background: rgba(51, 112, 255, 0.1);
}
&:hover {
background: rgba(51,112,255,.1);
background: rgba(51, 112, 255, 0.1);
}
}
.custom-popover-dark {
min-width: 50px!important;
min-width: 50px !important;
background: @side-content-background !important;
padding: 0px 4px 0 4px !important;
border: 1px solid @side-outline-border-color !important;
}
.custom-popover-light {
min-width: 50px!important;
min-width: 50px !important;
background: @side-content-background-light !important;
padding: 0px 4px 0 4px !important;
border: 1px solid @side-outline-border-color-light !important;
@ -235,7 +231,7 @@ body {
border-radius: 4px;
&:hover {
background: rgba(235, 235, 235, 0.10);
background: rgba(235, 235, 235, 0.1);
}
&:active {
@ -281,7 +277,7 @@ body {
}
.primary-color {
color: var(--ed-color-primary, #3370FF);
color: var(--ed-color-primary, #3370ff);
}
// .ed-drawer__footer {
@ -298,7 +294,6 @@ body {
display: none;
}
.create-dialog {
.ed-form-item {
margin-bottom: 16px;
@ -323,7 +318,6 @@ em {
text-align: left !important;
}
.cell {
.is-text {
.ed-icon {
@ -337,28 +331,28 @@ em {
max-height: 100vh;
overflow-y: auto;
background: none !important;
.ed-dialog__header{
.ed-dialog__header {
padding: 0px;
.ed-dialog__headerbtn{
.ed-dialog__headerbtn {
.ed-icon {
font-size: 24px;
color: white;
}
background: rgba(31, 35, 41, 0.90);
background: rgba(31, 35, 41, 0.9);
height: 48px;
width: 48px;
top:24px;
top: 24px;
right: 24px;
padding: 12px;
border-radius: 50%;
&:hover {
background: #646A73;
background: #646a73;
}
}
}
.ed-dialog__body{
.ed-dialog__body {
padding: 0px;
background-color: #1F232999;
background-color: #1f232999;
}
}
@ -367,3 +361,31 @@ em {
width: 16px !important;
height: 12px !important;
}
.color-panel {
background: #3370ff;
}
.color-dashboard {
background: #3370ff;
}
.color-screen {
background: rgb(0, 214, 185);
}
.color-dataV {
background: rgb(0, 214, 185);
}
.color-dataset {
background: rgb(22, 192, 255);
}
.color-datasource {
background: rgb(127, 59, 246);
}
.ed-table {
--ed-table-row-hover-bg-color: #e8e9e9 !important;
}

View File

@ -198,14 +198,6 @@ export function getCanvasStyle(canvasStyleData) {
return style
}
// export function createGroupStyle(groupComponent) {
// const parentStyle = groupComponent.style
// groupComponent.propValue.forEach(component => {
// component.style.left = component.style.left - parentStyle.left
// component.style.top = component.style.top - parentStyle.top
// })
// }
export function createGroupStyle(groupComponent) {
const parentStyle = groupComponent.style
groupComponent.propValue.forEach(component => {

View File

@ -171,11 +171,11 @@ const update = (licKey: string) => {
</div>
<div class="item">
<div class="label">{{ $t('about.serial_no') }}</div>
<div class="value">{{ license.serialNo }}</div>
<div class="value">{{ license.serialNo || '-' }}</div>
</div>
<div class="item">
<div class="label">{{ $t('about.remark') }}</div>
<div class="value ellipsis">{{ license.remark }}</div>
<div class="value ellipsis">{{ license.remark || '-' }}</div>
</div>
<div v-if="isAdmin" style="margin-top: 24px" class="lic_rooter">
@ -220,7 +220,7 @@ const update = (licKey: string) => {
margin-top: -7px;
.item {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 16px;
font-style: normal;
font-weight: 400;

View File

@ -264,22 +264,6 @@ onMounted(() => {
<span class="set-text-info" :class="{ 'set-text-info-dark': themes === 'dark' }">
已设置
</span>
<!-- <el-button
class="circle-button font14"
:title="t('chart.delete')"
:class="'label-' + props.themes"
text
size="small"
:style="{ width: '24px', marginLeft: '6px' }"
@click="linkageSetOpen"
>
<template #icon>
<el-icon size="14px">
<Icon name="icon_delete-trash_outlined" />
</el-icon>
</template>
</el-button>-->
</template>
<el-button
class="circle-button font14"
@ -406,7 +390,7 @@ span {
}
.label-dark {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
line-height: 20px;

View File

@ -318,7 +318,7 @@ span {
}
.label-dark {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
line-height: 20px;

View File

@ -767,7 +767,7 @@ span {
}
}
.label-dark {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
line-height: 20px;

View File

@ -479,7 +479,7 @@ watch(
}
.remark-label {
color: var(--N600, #646a73);
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 12px;
font-style: normal;
font-weight: 400;

View File

@ -554,6 +554,7 @@ onMounted(() => {
<el-checkbox
:disabled="!formatterEditable"
v-model="curSeriesFormatter.show"
:effect="themes"
size="small"
label="quota"
@change="changeTooltipAttr('seriesTooltipFormatter', true)"

View File

@ -202,7 +202,7 @@ span {
:deep(span) {
color: var(--N900, #1f2329);
/* 中文/桌面端/正文 14 22 Regular */
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -412,7 +412,7 @@ span {
:deep(span) {
color: var(--N900, #1f2329);
/* 中文/桌面端/正文 14 22 Regular */
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -187,13 +187,6 @@ const getFields = (id, chartId) => {
state.quotaData = []
}
}
watch(
[() => state.searchField],
newVal => {
fieldFilter(newVal[0])
},
{ deep: true }
)
const chartStyleShow = computed(() => {
return view.value.type !== 'richText'
@ -263,39 +256,39 @@ const queryList = computed(() => {
})
const quotaData = computed(() => {
let result = JSON.parse(JSON.stringify(state.quota))
if (view.value?.type === 'table-info') {
return state.quota?.filter(item => item.id !== '-1')
result = result?.filter(item => item.id !== '-1')
}
return state.quota
if (state.searchField) {
result = result.filter(item =>
item.name.toLowerCase().includes(state.searchField.toLowerCase())
)
}
return result
})
provide('quotaData', quotaData)
const dimensionData = computed(() => {
let result = JSON.parse(JSON.stringify(state.dimensionData))
if (state.searchField) {
result = result.filter(item =>
item.name.toLowerCase().includes(state.searchField.toLowerCase())
)
}
return result
})
const realQuota = computed(() => {
let result = JSON.parse(JSON.stringify(state.quota))
if (view.value?.type === 'table-info') {
result = result?.filter(item => item.id !== '-1')
}
return result
})
provide('quotaData', realQuota)
const startToMove = (e, item) => {
e.dataTransfer.setData('dimension', JSON.stringify({ ...item, datasetId: view.value.tableId }))
}
const fieldFilter = val => {
if (val && val !== '') {
state.dimensionData = JSON.parse(
JSON.stringify(
state.dimension.filter(ele => {
return ele.name.toLocaleLowerCase().includes(val.toLocaleLowerCase())
})
)
)
state.quotaData = JSON.parse(
JSON.stringify(
state.quota.filter(ele => {
return ele.name.toLocaleLowerCase().includes(val.toLocaleLowerCase())
})
)
)
} else {
state.dimensionData = JSON.parse(JSON.stringify(state.dimension))
state.quotaData = JSON.parse(JSON.stringify(state.quota))
}
}
const dimensionItemChange = () => {
recordSnapshotInfo('calcData')
// do dimensionItemChange
@ -1853,7 +1846,7 @@ const onRefreshChange = val => {
<label>{{ t('chart.dimension') }}</label>
<el-scrollbar class="drag-list">
<draggable
:list="state.dimensionData"
:list="dimensionData"
:group="dsFieldDragOptions.group"
:move="onMove"
item-key="id"
@ -2233,7 +2226,7 @@ const onRefreshChange = val => {
height: 35px;
line-height: 35px;
color: #3370ff;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 12px;
font-style: normal;
font-weight: 500;
@ -3097,7 +3090,7 @@ span {
margin-bottom: 16px !important;
.text {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
@ -3106,7 +3099,7 @@ span {
--ed-input-height: 32px;
:deep(.ed-input__inner) {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
@ -3117,7 +3110,7 @@ span {
:deep(.ed-form-item__label) {
color: #1f2329;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -4,6 +4,7 @@ import { parseJson } from '../../../util'
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
import { useI18n } from '@/hooks/web/useI18n'
import { isNumber } from 'lodash-es'
const { t } = useI18n()
@ -70,17 +71,14 @@ export class TableInfo extends S2ChartView<TableSheet> {
if (value === null || value === undefined) {
return value
}
if (f.groupType === 'd') {
if (f.groupType === 'd' || !isNumber(value)) {
return value
} else {
if (f.formatterCfg) {
const v = valueFormatter(value, f.formatterCfg)
return v.includes('NaN') ? value : v
} else {
const v = valueFormatter(value, formatterItem)
return v.includes('NaN') ? value : v
}
}
let formatCfg = f.formatterCfg
if (!formatCfg) {
formatCfg = formatterItem
}
return valueFormatter(value, formatCfg)
}
})
})

View File

@ -5,6 +5,7 @@ import { formatterItem, valueFormatter } from '@/views/chart/components/js/forma
import { getCurrentField } from '@/views/chart/components/js/panel/common/common_table'
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
import { useI18n } from '@/hooks/web/useI18n'
import { isNumber } from 'lodash-es'
const { t } = useI18n()
/**
@ -70,11 +71,14 @@ export class TableNormal extends S2ChartView<TableSheet> {
if (value === null || value === undefined) {
return value
}
if (f.formatterCfg) {
return valueFormatter(value, f.formatterCfg)
} else {
return valueFormatter(value, formatterItem)
if (f.groupType === 'd' || !isNumber(value)) {
return value
}
let formatCfg = f.formatterCfg
if (!formatCfg) {
formatCfg = formatterItem
}
return valueFormatter(value, formatCfg)
}
})
})

View File

@ -165,17 +165,6 @@ export function getColors(chart, colors, reset) {
} else {
if (chart.data) {
const data = chart.data.data
// data 的维度值需要根据自定义顺序排序
// let customSortData
// if (Object.prototype.toString.call(chart.customSort) === '[object Array]') {
// customSortData = JSON.parse(JSON.stringify(chart.customSort))
// } else {
// customSortData = JSON.parse(chart.customSort)
// }
// if (customSortData && customSortData.length > 0) {
// data = customSort(customSortData, data)
// }
for (let i = 0; i < data.length; i++) {
const s = data[i]
seriesColors.push({

View File

@ -10,7 +10,8 @@ import {
shallowRef,
ShallowRef,
toRaw,
toRefs
toRefs,
watch
} from 'vue'
import { getData } from '@/api/chart'
import chartViewManager from '@/views/chart/components/js/panel'
@ -149,10 +150,6 @@ const renderChart = (viewInfo: Chart, resetPageInfo: boolean) => {
initScroll()
}
const pageColor = computed(() => {
const text = view.value?.customStyle?.text
return text.color ?? 'white'
})
const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
const customAttr = chart.customAttr
if (chart.type !== 'table-info' || customAttr.basicStyle.tablePageMode !== 'page') {
@ -172,7 +169,7 @@ const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
}
}
let scrollTimer
let scrollTimer: number
let scrollTop = 0
const initScroll = () => {
clearInterval(scrollTimer)
@ -216,7 +213,7 @@ const showPage = computed(() => {
const handleCurrentChange = pageNum => {
let extReq = { goPage: pageNum }
if (chartExtRequest) {
if (chartExtRequest.value) {
extReq = { ...extReq, ...chartExtRequest.value }
}
const chart = { ...view.value, chartExtRequest: extReq }
@ -317,7 +314,7 @@ const resize = (width, height) => {
}
const preSize = [0, 0]
const TOLERANCE = 1
let resizeObserver
let resizeObserver: ResizeObserver
onMounted(() => {
isDataEaseBi.value = !!window.DataEaseBi
resizeObserver = new ResizeObserver(([entry] = []) => {
@ -359,13 +356,12 @@ onBeforeUnmount(() => {
<div style="height: 100%" :id="containerId"></div>
</div>
<div class="table-page-info" v-if="showPage && !isError">
<div :style="{ color: pageColor }">{{ state.pageInfo.total }}</div>
<div>{{ state.pageInfo.total }}</div>
<el-pagination
class="table-page-content"
layout="prev, pager, next"
v-model:page-size="state.pageInfo.pageSize"
v-model:current-page="state.pageInfo.currentPage"
:style="{ color: pageColor }"
:pager-count="5"
:total="state.pageInfo.total"
@update:current-page="handleCurrentChange"
@ -396,14 +392,16 @@ onBeforeUnmount(() => {
display: flex;
width: 100%;
justify-content: space-between;
color: grey;
:deep(.table-page-content) {
button {
color: inherit;
button,
button[disabled] {
color: grey;
background: transparent !important;
}
ul li {
&:not(.is-active) {
color: inherit;
color: grey;
}
background: transparent !important;
}

View File

@ -270,8 +270,8 @@ const initTitle = () => {
}
}
const drillJump = index => {
state.drillClickDimensionList = state.drillClickDimensionList.slice(0, index)
const drillJump = (index: number) => {
state.drillClickDimensionList.splice(index)
view.value.chartExtRequest = filter()
calcData(view.value)
}

View File

@ -409,7 +409,7 @@ const emits = defineEmits(['finish'])
margin-bottom: 8px;
}
span {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-weight: 400;
line-height: 22px;

View File

@ -374,7 +374,7 @@ defineExpose({
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="addOperation('newLeaf', null, 'leaf', true)">
<el-icon class="handle-icon">
<el-icon :class="`handle-icon color-${curCanvasType}`">
<Icon :name="dvSvgType"></Icon>
</el-icon>
空白新建
@ -427,7 +427,7 @@ defineExpose({
<el-icon style="font-size: 18px" v-else-if="curCanvasType === 'dashboard'">
<Icon name="dv-dashboard-spine"></Icon>
</el-icon>
<el-icon class="icon-screen-new" style="font-size: 18px" v-else>
<el-icon class="icon-screen-new color-dataV" style="font-size: 18px" v-else>
<Icon name="icon_operation-analysis_outlined"></Icon>
</el-icon>
<span :title="node.label" class="label-tooltip">{{ node.label }}</span>
@ -579,7 +579,6 @@ defineExpose({
}
.icon-screen-new {
background: #3370ff;
border-radius: 4px;
color: #fff;
padding: 3px;

View File

@ -33,7 +33,7 @@ const timestampFormatDate = value => {
<style lang="less" scoped>
.info-card {
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
padding-left: 4px;
font-weight: 400;

View File

@ -85,7 +85,6 @@ watch(
</el-popover>
</div>
<div class="canvas-opt-button">
<!-- <el-button type="primary" @click="download()">导出</el-button>-->
<el-button @click="preview()">
<template #icon>
<icon name="icon_pc_outlined"></icon>

View File

@ -15,7 +15,6 @@ import { XpackComponent } from '@/components/plugin'
import { logoutHandler } from '@/utils/logout'
import DeImage from '@/assets/login-desc-de.png'
import elementResizeDetectorMaker from 'element-resize-detector'
import PreheatImage from '@/assets/preheat.png'
import { isLarkPlatform } from '@/utils/utils'
const { wsCache } = useCache()
const appStore = useAppStoreWithOut()
@ -145,16 +144,6 @@ const cleanPlatformFlag = () => {
}
const preheat = ref(true)
const svg = `
<path class="path" d="
M 30 15
L 28 17
M 25.61 25.61
A 15 15, 0, 0, 1, 15 30
A 15 15, 0, 1, 1, 27.99 7.5
L 15 15
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
`
const showLoginErrorMsg = () => {
if (!loginErrorMsg.value) {
return
@ -209,13 +198,9 @@ onMounted(() => {
ref="loginContainer"
class="preheat-container"
v-loading="true"
element-loading-text="Loading..."
:element-loading-spinner="svg"
element-loading-svg-view-box="-10, -10, 50, 50"
element-loading-background="rgba(122, 122, 122, 0.8)"
>
<el-image class="preheat-image" fit="cover" :src="PreheatImage" />
</div>
element-loading-text="登录中..."
element-loading-background="#F5F6F7"
/>
<div v-show="contentShow" class="login-background" v-loading="duringLogin">
<div class="login-container" ref="loginContainer">
<div class="login-image-content" v-loading="!axiosFinished" v-if="showLoginImage">
@ -354,10 +339,6 @@ onMounted(() => {
background: #000;
position: absolute;
z-index: 100;
.preheat-image {
width: 98%;
height: 98%;
}
}
.login-background {
background-color: #f5f7fa;
@ -426,7 +407,7 @@ onMounted(() => {
text-align: center;
margin-top: 8px;
color: #646a73;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
@ -464,7 +445,7 @@ onMounted(() => {
:deep(.ed-divider__text) {
color: #8f959e;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 12px;
font-style: normal;
font-weight: 400;

View File

@ -0,0 +1,140 @@
<script lang="ts" setup>
import { ref, reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { cloneDeep } from 'lodash-es'
import request from '@/config/axios'
import { rsaEncryp } from '@/utils/encryption'
import { ElMessage } from 'element-plus-secondary'
import { logoutHandler } from '@/utils/logout'
import { CustomPassword } from '@/components/custom-password'
const { t } = useI18n()
const defaultForm = {
pwd: '',
newPwd: '',
confirm: ''
}
const pwdForm = reactive(cloneDeep(defaultForm))
const validatePwd = (_: any, value: any, callback: any) => {
if (value === pwdForm.pwd) {
callback(new Error('新旧密码不能相同'))
}
const pattern =
/^.*(?=.{6,20})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[~!@#$%^&*()_+\-\={}|":<>?`[\];',.\/])[a-zA-Z0-9~!@#$%^&*()_+\-\={}|":<>?`[\];',.\/]*$/
const regep = new RegExp(pattern)
if (!regep.test(value)) {
const msg = t('user.pwd_pattern_error')
callback(new Error(msg))
} else {
callback()
}
}
const validateConfirmPwd = (_: any, value: any, callback: any) => {
if (value !== pwdForm.newPwd) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
}
const rule = {
pwd: [
{
required: true,
message: t('common.require'),
trigger: 'blur'
},
{
min: 6,
max: 20,
message: t('commons.input_limit', [6, 20]),
trigger: 'blur'
}
],
newPwd: [
{
required: true,
message: t('common.require'),
trigger: 'blur'
},
{ validator: validatePwd, trigger: 'blur' }
],
confirm: [
{
required: true,
message: t('common.require'),
trigger: 'blur'
},
{
min: 6,
max: 20,
message: t('commons.input_limit', [6, 20]),
trigger: 'blur'
},
{ validator: validateConfirmPwd, trigger: 'blur' }
]
}
const updatePwdForm = ref()
const save = () => {
updatePwdForm.value.validate(val => {
if (val) {
const pwd = rsaEncryp(pwdForm.pwd)
const newPwd = rsaEncryp(pwdForm.newPwd)
request.post({ url: '/user/modifyPwd', data: { pwd, newPwd } }).then(() => {
ElMessage.success('修改成功,请重新登录')
logoutHandler()
})
}
})
}
</script>
<template>
<el-form
ref="updatePwdForm"
require-asterisk-position="right"
:model="pwdForm"
:rules="rule"
class="mt16"
label-width="80px"
label-position="top"
>
<el-form-item label="原始密码" prop="pwd">
<CustomPassword
v-model="pwdForm.pwd"
show-password
type="password"
placeholder="请输入原始密码"
/>
</el-form-item>
<el-form-item label="新密码" prop="newPwd">
<CustomPassword
v-model="pwdForm.newPwd"
show-password
type="password"
placeholder="请输入新密码"
/>
</el-form-item>
<el-form-item label="确认密码" prop="confirm">
<CustomPassword
v-model="pwdForm.confirm"
show-password
type="password"
placeholder="请输入确认密码"
/>
</el-form-item>
<el-button style="margin-top: 12px" @click="save" type="primary">
{{ t('common.save') }}
</el-button>
</el-form>
</template>
<style lang="less" scoped>
.mt16 {
margin-top: 16px;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="user-center flex-align-center">
<div class="user-center-container">
<div class="user-tabs">
<div class="tabs-title flex-align-center">用户中心</div>
<el-divider />
<div class="list-item_primary active">
{{ t('user.change_password') }}
</div>
</div>
<div class="user-info">
<div class="base-info">
<div class="info-title flex-align-center">
<span class="title">
{{ t('user.change_password') }}
</span>
</div>
<update-pwd />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import UpdatePwd from './UpdatePwd.vue'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
</script>
<style lang="less" scoped>
.user-center {
width: 100%;
flex-direction: column;
padding-top: 24px;
.user-center-container {
display: flex;
font-family: PingFang SC;
font-style: normal;
}
.user-tabs {
width: 200px;
height: 201px;
border-radius: 4px;
background: #fff;
padding: 16px;
.list-item_primary {
padding: 9px 8px;
}
.ed-divider {
margin: 4px 0;
border-color: rgba(31, 35, 41, 0.15);
}
.tabs-title {
padding-left: 8px;
color: #8d9199;
font-family: PingFang SC;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 22px;
height: 40px;
}
}
.user-info {
margin-left: 16px;
width: 864px;
height: 326px;
.base-info {
& + .base-info {
margin-top: 12px;
.bind-info {
margin-top: 16px;
display: flex;
align-items: center;
width: 100%;
padding: 16px 24px 16px 24px;
border-radius: 4px;
border: 1px solid #dee0e3;
.bind {
font-size: 48px;
margin-right: 12px;
}
.info {
font-family: PingFang SC;
font-style: normal;
font-weight: 400;
width: 80%;
.name {
color: #1f2329;
font-size: 16px;
line-height: 24px;
font-weight: 500;
width: 100%;
}
.tip {
color: #646a73;
font-size: 14px;
line-height: 22px;
max-width: 600px;
white-space: pre-wrap;
}
}
.delete {
margin-left: auto;
}
}
}
padding: 20px 24px 24px 24px;
border-radius: 4px;
background: #fff;
.role {
& + .role {
margin-left: 4px;
}
display: inline-flex;
height: 20px;
padding: 0 6px;
align-items: center;
font-size: 12px;
color: #2b5fd9;
border-radius: 2px;
background: rgba(51, 112, 255, 0.2);
}
.info-title {
.ed-button {
margin-left: auto;
}
.title {
color: #1f2329;
font-size: 16px;
font-weight: 500;
line-height: 24px;
}
}
}
}
.base-info-item {
margin-top: 16px;
font-size: 14px;
font-weight: 400;
line-height: 22px;
width: 100%;
.label {
color: #646a73;
}
.value {
margin-top: 4px;
color: #1f2329;
}
}
.mr12 {
margin-top: 12px;
}
}
</style>
<style lang="less">
.qr-code-dialog {
font-family: PingFang SC;
font-style: normal;
.ed-dialog__body {
display: flex;
flex-direction: column;
align-items: center;
}
.qr-code-img {
margin-top: 16px;
display: inline-block;
padding: 8px 12px;
img {
width: 184px;
height: 184px;
}
border-radius: 8px;
border: 1px solid #bbbfc4;
}
.refresh-login {
margin: 0 auto;
margin-top: 9px;
color: #646a73;
font-size: 14px;
font-weight: 400;
line-height: 22px;
.ed-icon {
margin-left: 4px;
}
}
}
</style>

View File

@ -44,6 +44,20 @@ const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
if (
state.form.dsExecuteTime === 'minute' &&
(Number(state.form.dsIntervalTime) < 1 || Number(state.form.dsIntervalTime) > 59)
) {
ElMessage.error('分钟超出范围【1-59】')
return
}
if (
state.form.dsExecuteTime === 'hour' &&
(Number(state.form.dsIntervalTime) < 1 || Number(state.form.dsIntervalTime) > 23)
) {
ElMessage.error('小时超出范围【1-23】')
return
}
const param = buildSettingList()
if (param.length < 2) {
return
@ -153,34 +167,6 @@ defineExpose({
</div>
<div v-else />
</el-form-item>
<!-- <el-form-item label="禁止扫码创建用户" prop="autoCreateUser">
<el-switch v-model="state.form.autoCreateUser" />
</el-form-item> -->
<!-- <el-form-item label="数据源检测时间间隔" prop="dsIntervalTime">
<div class="ds-task-form-inline">
<span></span>
<el-input-number
v-model="state.form.dsIntervalTime"
autocomplete="off"
step-strictly
class="text-left"
:min="1"
:placeholder="t('common.inputText')"
controls-position="right"
type="number"
/>
<el-select v-model="state.form.dsExecuteTime">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<span class="ds-span">执行一次</span>
</div>
</el-form-item> -->
</el-form>
<template #footer>
<span class="dialog-footer">

View File

@ -139,7 +139,7 @@ defineExpose({
}
.pwd {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-weight: 400;
line-height: 22px;
@ -158,7 +158,7 @@ defineExpose({
padding: 0 20px;
color: #1f2329;
text-align: center;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -7,7 +7,6 @@
<div class="container-sys-param">
<map-setting v-if="activeName === 'map'" />
<basic-info v-if="activeName === 'basic'" />
<!-- <email-info v-if="activeName === 'email'" /> -->
</div>
</div>
</template>
@ -32,7 +31,7 @@ const activeName = ref('basic')
.router-title {
color: #1f2329;
font-feature-settings: 'clig' off, 'liga' off;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 20px;
font-style: normal;
font-weight: 500;

View File

@ -40,6 +40,7 @@
<template #default="{ node, data }">
<span class="custom-tree-node" :class="{ 'is-disabled': node.disabled || data.root }">
<span
class="geo-name-span"
:title="data.name"
v-html="data.colorName && keyword ? data.colorName : data.name"
/>
@ -304,14 +305,19 @@ loadTreeData(true)
padding-right: 4px;
overflow: hidden;
justify-content: space-between;
.geo-name-span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.geo-operate-container {
display: none;
}
&:hover {
.geo-operate-container {
display: contents;
display: inline-flex;
padding-left: 4px;
}
}
}

View File

@ -17,12 +17,12 @@ const dialogVisible = ref(false)
const loadingInstance = ref(null)
const geoForm = ref<FormInstance>()
const geoFile = ref()
const fileName = ref()
const state = reactive({
form: reactive<GeometryFrom>({
pid: null,
code: null,
name: null
name: null,
fileName: null
}),
treeData: []
})
@ -53,6 +53,13 @@ const rule = reactive<FormRules>({
message: t('common.require'),
trigger: 'blur'
}
],
fileName: [
{
required: true,
message: t('common.require'),
trigger: 'blur'
}
]
})
@ -63,7 +70,7 @@ const edit = (pid?: string) => {
state.form.code = null
state.form.name = null
geoFile.value = null
fileName.value = null
state.form.fileName = null
dialogVisible.value = true
}
@ -71,7 +78,7 @@ const emits = defineEmits(['saved'])
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
await formEl.validate(valid => {
if (valid) {
const param = { ...state.form }
const formData = buildFormData(geoFile.value, param)
@ -96,7 +103,6 @@ const submitForm = async (formEl: FormInstance | undefined) => {
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
geoFile.value = null
fileName.value = null
formEl.resetFields()
dialogVisible.value = false
}
@ -119,7 +125,7 @@ const handleError = () => {
}
const setFile = (options: UploadRequestOptions) => {
geoFile.value = options.file
fileName.value = options.file.name
state.form.fileName = options.file.name
}
const uploadValidate = file => {
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1)
@ -185,7 +191,7 @@ defineExpose({
</el-form-item>
<div class="geo-label-mask" />
<el-form-item label="坐标文件">
<el-form-item label="坐标文件" prop="fileName">
<el-upload
class="upload-geo"
action=""
@ -196,14 +202,18 @@ defineExpose({
:show-file-list="false"
:http-request="setFile"
>
<el-input :placeholder="t('userimport.placeholder')" readonly v-model="fileName">
<el-input
:placeholder="t('userimport.placeholder')"
readonly
v-model="state.form.fileName"
>
<template #suffix>
<el-icon>
<Icon name="icon_upload_outlined" />
</el-icon>
</template>
<template #prefix>
<el-icon v-if="!!fileName">
<el-icon v-if="!!state.form.fileName">
<Icon name="de-json" />
</el-icon>
</template>

View File

@ -2,4 +2,5 @@ export interface GeometryFrom {
pid?: string
code?: string
name?: string
fileName?: string
}

View File

@ -371,7 +371,7 @@ onMounted(() => {
.insert-filter {
display: inline-block;
font-weight: 400 !important;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer;
@ -400,7 +400,7 @@ onMounted(() => {
.insert {
display: inline-block;
font-weight: 400 !important;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer;

View File

@ -492,7 +492,7 @@ onMounted(() => {
.insert-filter {
display: inline-block;
font-weight: 400 !important;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer;
@ -525,7 +525,7 @@ onMounted(() => {
display: inline-block;
font-size: 34px;
font-weight: 400 !important;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer;

View File

@ -14,10 +14,10 @@
{{ template.title }}
</el-row>
<el-row class="template-button">
<el-button size="mini" style="width: 100px" @click="templateInnerPreview">{{
<el-button size="mini" style="width: calc(50% - 18px)" @click="templateInnerPreview">{{
t('visualization.preview')
}}</el-button>
<el-button size="mini" style="width: 100px" type="primary" @click="apply">{{
<el-button size="mini" style="width: calc(50% - 18px)" type="primary" @click="apply">{{
t('visualization.apply')
}}</el-button>
</el-row>

View File

@ -148,7 +148,7 @@ const handleCommand = key => {
.de-model-text {
margin-left: 8px;
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 400;
font-size: 14px;

View File

@ -153,7 +153,7 @@ defineExpose({
align-items: center;
border-radius: 4px;
color: var(--deTextPrimary, #1f2329);
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 500;
font-size: 14px;

View File

@ -592,7 +592,7 @@ onMounted(() => {
.active-template {
height: 56px;
padding: 0px 24px;
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
font-weight: 500;
font-size: 16px;
@ -618,7 +618,7 @@ onMounted(() => {
.router-title {
color: #1f2329;
font-feature-settings: 'clig' off, 'liga' off;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 20px;
font-style: normal;
font-weight: 500;

View File

@ -36,7 +36,7 @@ const { t } = useI18n()
<style lang="less" scoped>
.info-card {
font-family: 'PingFang SC';
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-style: normal;
padding-left: 4px;
font-weight: 400;

View File

@ -149,7 +149,7 @@ const del = (index, child) => {
z-index: 10;
.operate-title {
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
word-wrap: break-word;
box-sizing: border-box;
color: rgba(0, 0, 0, 0.65);

View File

@ -553,7 +553,7 @@ const emits = defineEmits(['update:item', 'del'])
}
.bottom-line {
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-variant: tabular-nums;
font-feature-settings: 'tnum';
word-wrap: break-word;
@ -601,7 +601,7 @@ const emits = defineEmits(['update:item', 'del'])
border-radius: 0;
box-shadow: none;
height: 26px;
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
word-wrap: break-word;
text-align: left;
color: rgba(0, 0, 0, 0.65);
@ -714,8 +714,8 @@ const emits = defineEmits(['update:item', 'del'])
}
.ed-input {
font-family: Alibaba-PuHuiTi-Regular, Helvetica Neue, Helvetica, Arial, PingFang SC,
Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: Alibaba-PuHuiTi-Regular, Helvetica Neue, Helvetica, Arial,
'阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
box-sizing: border-box;
margin: 0;
color: rgba(0, 0, 0, 0.65);
@ -748,7 +748,7 @@ const emits = defineEmits(['update:item', 'del'])
box-shadow: none;
border: 1px solid rgba(0, 0, 0, 0.05);
.mod-left {
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
color: rgba(0, 0, 0, 0.65);
font-size: 12px;
vertical-align: top;
@ -794,7 +794,7 @@ const emits = defineEmits(['update:item', 'del'])
border-left: 1px solid hsla(0, 0%, 59%, 0.1);
}
.autochecker-list {
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei, sans-serif;
color: rgba(0, 0, 0, 0.65);
box-sizing: border-box;
width: 100%;
@ -839,7 +839,8 @@ const emits = defineEmits(['update:item', 'del'])
}
label {
font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei,
sans-serif;
font-size: 12px;
direction: ltr;
color: #333;

View File

@ -858,7 +858,7 @@ const mousedownDrag = () => {
height: 100%;
width: 240px;
float: left;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
border-right: 1px solid rgba(31, 35, 41, 0.15);
.list-item_primary {
@ -960,7 +960,7 @@ const mousedownDrag = () => {
float: right;
height: calc(100vh - 156px);
.sql-result {
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
overflow-y: auto;
box-sizing: border-box;
@ -1122,7 +1122,7 @@ const mousedownDrag = () => {
.sql-tips {
color: #646a73;
text-align: center;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
@ -1146,7 +1146,7 @@ const mousedownDrag = () => {
.num {
margin-left: auto;
color: #646a73;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;
@ -1235,7 +1235,7 @@ const mousedownDrag = () => {
background: #e1eaff;
position: relative;
padding: 9px 0 9px 40px;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-weight: 400;

View File

@ -498,7 +498,7 @@ initFunction()
& > :nth-child(2) {
margin: 0 -0.67px 0 2px;
color: #f54a45;
font-family: PingFang SC;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px;
font-style: normal;
font-weight: 400;

Some files were not shown because too many files have changed in this diff Show More