refactor: merge dev

This commit is contained in:
taojinlong 2023-01-30 15:14:35 +08:00
commit 87f3acbf14
87 changed files with 1969 additions and 1005 deletions

View File

@ -1,543 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dataease-server</artifactId>
<groupId>io.dataease</groupId>
<version>1.18.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>backend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<shiro.version>1.9.1</shiro.version>
<java.version>1.8</java.version>
<graalvm.version>20.1.0</graalvm.version>
<jwt.version>3.12.1</jwt.version>
<buji.version>4.0.0</buji.version>
<pac4j.version>3.3.0</pac4j.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- flyway -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>[1.10.0,)</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.fit2cloud</groupId>
<artifactId>quartz-spring-boot-starter</artifactId>
<version>0.0.7</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
<!--xpath不加这个依赖会报错-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<!--开启 cache 缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<scope>test</scope>
</dependency>
<!-- ehcache 缓存 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-interface</artifactId>
<version>1.18.1</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-view</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>dataease-plugin-datasource</artifactId>
<version>1.18.1</version>
</dependency>
<!-- kettle及数据源依赖 -->
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-core</artifactId>
<version>8.3.0.18-1112</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>pentaho-kettle</groupId>
<artifactId>kettle-engine</artifactId>
<version>8.3.0.18-1112</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>pentaho</groupId>
<artifactId>metastore</artifactId>
<version>8.3.0.18-1112</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.pentaho.di.plugins</groupId>
<artifactId>pdi-engine-configuration-impl</artifactId>
<version>8.3.0.7-683</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>jconsole</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>ru.yandex.qatools.ashot</groupId>
<artifactId>ashot</artifactId>
<version>1.5.4</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>static/**/*.woff</exclude>
<exclude>static/**/*.woff2</exclude>
<exclude>static/**/*.ttf</exclude>
<exclude>static/**/*.ico</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/**/*.woff</include>
<include>static/**/*.woff2</include>
<include>static/**/*.ttf</include>
<include>static/**/*.ico</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>src/main/resources/static</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
<fileset>
<directory>src/main/resources/templates</directory>
<includes>
<include>**</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Overlay guacamole-common-js (zip) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.3.8</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>whole</id>
<properties>
<profiles.active>whole</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<?m2e execute onConfiguration?>
<id>main-class-placement</id>
<phase>generate-resources</phase>
<configuration>
<target>
<move todir="src/main/resources/static">
<fileset dir="../frontend/dist">
<exclude name="*.html"/>
</fileset>
</move>
<move todir="src/main/resources/templates">
<fileset dir="../frontend/dist">
<include name="*.html"/>
</fileset>
</move>
<copy todir="src/main/resources/static/de-app">
<fileset dir="../mobile/dist">
<exclude name="*.html"/>
</fileset>
</copy>
<copy file="../mobile/dist/index.html"
tofile="src/main/resources/templates/app.html"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>stage</id>
<properties>
<profiles.active>stage</profiles.active>
</properties>
</profile>
</profiles>
<repositories>
<repository>
<id>pentaho-public</id>
<name>Pentaho Public</name>
<url>https://nexus.pentaho.org/content/groups/omni</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -1,5 +1,8 @@
package io.dataease.commons.license;
import lombok.Data;
@Data
public class F2CLicense {
private String corporation;
@ -10,61 +13,6 @@ public class F2CLicense {
private String edition;
private Long count;
public String getCorporation() {
return corporation;
}
public void setCorporation(String corporation) {
this.corporation = corporation;
}
public String getExpired() {
return expired;
}
public void setExpired(String expired) {
this.expired = expired;
}
public String getLicenseVersion() {
return licenseVersion;
}
public void setLicenseVersion(String licenseVersion) {
this.licenseVersion = licenseVersion;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public Long getGenerateTime() {
return generateTime;
}
public void setGenerateTime(Long generateTime) {
this.generateTime = generateTime;
}
public String getEdition() {
return edition;
}
public void setEdition(String edition) {
this.edition = edition;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
private String serialNo;
private String remark;
}

View File

@ -164,6 +164,9 @@ public class DatasourceController {
public ApiDefinition checkApiDatasource(@RequestBody Map<String, String> data) throws Exception {
ApiDefinition apiDefinition = new Gson().fromJson(new String(java.util.Base64.getDecoder().decode(data.get("data"))), new TypeToken<ApiDefinition>() {
}.getType());
if(data.keySet().contains("type") && data.get("type").equals("apiStructure")){
apiDefinition.setShowApiStructure(true);
}
return datasourceService.checkApiDatasource(apiDefinition);
}

View File

@ -8,6 +8,7 @@ import io.dataease.service.panel.PanelAppTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@ -57,7 +58,14 @@ public class PanelAppTemplateController {
@PostMapping("/nameCheck")
@I18n
public String nameCheck(@RequestBody PanelAppTemplateRequest request) {
return panelAppTemplateService.nameCheck(request);
return panelAppTemplateService.nameCheck(request);
}
@ApiOperation("移动")
@PostMapping("/move")
@I18n
public void move(@RequestBody PanelAppTemplateRequest request) {
panelAppTemplateService.move(request);
}
}

View File

@ -23,5 +23,8 @@ public class ApiDefinition {
private int previewNum = 10;
private int maxPreviewNum = 10;
private int serialNumber;
private boolean useJsonPath;
private String jsonPath;
private boolean showApiStructure;
}

View File

@ -17,4 +17,5 @@ public class ChartSeniorAssistDTO {
private String lineType;
private String color;
private DatasetTableField curField;
private String fontSize;
}

View File

@ -124,8 +124,8 @@
and configuration = #{configuration,jdbcType=LONGVARCHAR}
</if>
</where>
<if test="sort == null">
order by ${sort}
<if test="sort != null">
order by #{sort}
</if>
</select>

View File

@ -1,5 +1,6 @@
package io.dataease.listener;
import io.dataease.listener.util.CacheUtils;
import io.dataease.service.datasource.DatasourceService;
import io.dataease.service.dataset.DataSetTableService;
import io.dataease.service.engine.EngineService;
@ -25,7 +26,7 @@ public class DataSourceInitStartListener implements ApplicationListener<Applicat
datasourceService.initDsCheckJob();
dataSetTableService.updateDatasetTableStatus();
engineService.initSimpleEngine();
CacheUtils.removeAll("ENGINE");
}

View File

@ -16,10 +16,7 @@ import io.dataease.plugins.common.entity.GlobalTaskInstance;
import io.dataease.plugins.common.entity.XpackConditionEntity;
import io.dataease.plugins.common.entity.XpackGridRequest;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.email.dto.request.XpackEmailCreate;
import io.dataease.plugins.xpack.email.dto.request.XpackEmailTaskRequest;
import io.dataease.plugins.xpack.email.dto.request.XpackEmailViewRequest;
import io.dataease.plugins.xpack.email.dto.request.XpackPixelEntity;
import io.dataease.plugins.xpack.email.dto.request.*;
import io.dataease.plugins.xpack.email.dto.response.XpackTaskGridDTO;
import io.dataease.plugins.xpack.email.dto.response.XpackTaskInstanceDTO;
import io.dataease.plugins.xpack.email.service.EmailXpackService;
@ -165,6 +162,44 @@ public class XEmailTaskServer {
return xpackEmailCreate;
}
@DeRateLimiter
@PostMapping(value = "/screenpdf", produces = {MediaType.APPLICATION_PDF_VALUE})
public ResponseEntity<ByteArrayResource> screenpdf(@RequestBody XpackReportExportRequest request) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
String url = ServletUtils.domain() + "/#/previewScreenShot/" + request.getPanelId() + "/true";
byte[] bytes = null;
try {
String currentToken = ServletUtils.getToken();
Future<?> future = priorityExecutor.submit(() -> {
try {
return emailXpackService.printPdf(url, currentToken, buildPixel(request.getPixel()), request.isShowPageNo());
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
DEException.throwException("预览失败,请联系管理员");
}
return null;
}, 0);
Object object = future.get();
if (ObjectUtils.isNotEmpty(object)) {
bytes = (byte[]) object;
if (ArrayUtil.isNotEmpty(bytes)) {
String fileName = request.getPanelId() + ".pdf";
ByteArrayResource bar = new ByteArrayResource(bytes);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
ContentDisposition contentDisposition = ContentDisposition.parse("attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
headers.setContentDisposition(contentDisposition);
return new ResponseEntity(bar, headers, HttpStatus.OK);
}
}
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
DEException.throwException("预览失败,请联系管理员");
}
return null;
}
@DeRateLimiter
@PostMapping(value = "/screenshot", produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
public ResponseEntity<ByteArrayResource> screenshot(@RequestBody XpackEmailViewRequest request) {

View File

@ -81,8 +81,17 @@ public class XWecomServer {
return wecomXpackService.getQrParam();
}
@GetMapping("/callBackWithoutLogin")
public ModelAndView callBackWithoutLogin(@RequestParam("code") String code,@RequestParam("state") String state) {
return privateCallBack(code, state, true);
}
@GetMapping("/callBack")
public ModelAndView callBack(@RequestParam("code") String code, @RequestParam("state") String state) {
return privateCallBack(code, state, false);
}
private ModelAndView privateCallBack(String code, String state, Boolean withoutLogin) {
ModelAndView modelAndView = new ModelAndView("redirect:/");
HttpServletResponse response = ServletUtils.response();
WecomXpackService wecomXpackService = null;
@ -123,6 +132,12 @@ public class XWecomServer {
Cookie cookie_token = new Cookie("Authorization", token);
cookie_token.setPath("/");
if (withoutLogin) {
Cookie platformCookie = new Cookie("inOtherPlatform", "true");
platformCookie.setPath("/");
response.addCookie(platformCookie);
}
response.addCookie(cookie_token);
} catch (Exception e) {

View File

@ -125,7 +125,6 @@ public class ApiProvider extends Provider {
}
static public String execHttpRequest(ApiDefinition apiDefinition, int socketTimeout) throws Exception {
String response = "";
HttpClientConfig httpClientConfig = new HttpClientConfig();
httpClientConfig.setSocketTimeout(socketTimeout * 1000);
@ -135,7 +134,6 @@ public class ApiProvider extends Provider {
httpClientConfig.addHeader(header.get("name").toString(), header.get("value").toString());
}
}
if (apiDefinitionRequest.getAuthManager() != null
&& StringUtils.isNotBlank(apiDefinitionRequest.getAuthManager().getUsername())
&& StringUtils.isNotBlank(apiDefinitionRequest.getAuthManager().getPassword())
@ -188,27 +186,72 @@ public class ApiProvider extends Provider {
throw new Exception("该请求返回数据为空");
}
List<JSONObject> fields = new ArrayList<>();
String rootPath;
if (response.startsWith("[")) {
rootPath = "$[*]";
JSONArray jsonArray = JSONObject.parseArray(response);
for (Object o : jsonArray) {
handleStr(apiDefinition, o.toString(), fields, rootPath);
if (apiDefinition.isUseJsonPath() && !apiDefinition.isShowApiStructure()) {
List<LinkedHashMap> currentData = new ArrayList<>();
Object object = JsonPath.read(response, apiDefinition.getJsonPath());
if (object instanceof List) {
currentData = (List<LinkedHashMap>) object;
} else {
currentData.add((LinkedHashMap) object);
}
int i = 0;
for (LinkedHashMap data : currentData) {
if (i >= apiDefinition.getPreviewNum()) {
break;
}
if (i == 0) {
for (Object o : data.keySet()) {
JSONObject field = new JSONObject();
field.put("originName", o.toString());
field.put("name", o.toString());
field.put("type", "STRING");
field.put("checked", true);
field.put("size", 65535);
field.put("deExtractType", 0);
field.put("deType", 0);
field.put("extField", 0);
fields.add(field);
}
}
for (JSONObject field : fields) {
JSONArray array = field.getJSONArray("value");
if (array != null) {
array.add(Optional.ofNullable(data.get(field.getString("originName"))).orElse("").toString().replaceAll("\n", " ").replaceAll("\r", " "));
} else {
array = new JSONArray();
array.add(Optional.ofNullable(data.get(field.getString("originName"))).orElse("").toString().replaceAll("\n", " ").replaceAll("\r", " "));
}
field.put("value", array);
}
i++;
}
apiDefinition.setJsonFields(fields);
return apiDefinition;
} else {
rootPath = "$";
handleStr(apiDefinition, response, fields, rootPath);
}
for (JSONObject field : fields) {
if (field.containsKey("children") && CollectionUtils.isNotEmpty(field.getJSONArray("children"))) {
field.put("disabled", false);
String rootPath;
if (response.startsWith("[")) {
rootPath = "$[*]";
JSONArray jsonArray = JSONObject.parseArray(response);
for (Object o : jsonArray) {
handleStr(apiDefinition, o.toString(), fields, rootPath);
}
} else {
rootPath = "$";
handleStr(apiDefinition, response, fields, rootPath);
}
if (field.containsKey("children") && CollectionUtils.isEmpty(field.getJSONArray("children"))) {
field.put("disabled", true);
for (JSONObject field : fields) {
if (field.containsKey("children") && CollectionUtils.isNotEmpty(field.getJSONArray("children"))) {
field.put("disabled", false);
}
if (field.containsKey("children") && CollectionUtils.isEmpty(field.getJSONArray("children"))) {
field.put("disabled", true);
}
}
apiDefinition.setJsonFields(fields);
return apiDefinition;
}
apiDefinition.setJsonFields(fields);
return apiDefinition;
}
@ -362,9 +405,9 @@ public class ApiProvider extends Provider {
private List<String[]> fetchResult(String result, ApiDefinition apiDefinition) {
List<String[]> dataList = new LinkedList<>();
if (StringUtils.isNotEmpty(apiDefinition.getDataPath()) && CollectionUtils.isEmpty(apiDefinition.getJsonFields())) {
if(apiDefinition.isUseJsonPath()){
List<LinkedHashMap> currentData = new ArrayList<>();
Object object = JsonPath.read(result, apiDefinition.getDataPath());
Object object = JsonPath.read(result, apiDefinition.getJsonPath());
if (object instanceof List) {
currentData = (List<LinkedHashMap>) object;
} else {
@ -379,30 +422,49 @@ public class ApiProvider extends Provider {
}
dataList.add(row);
}
} else {
List<String> jsonPaths = apiDefinition.getFields().stream().map(DatasetTableFieldDTO::getJsonPath).collect(Collectors.toList());
Long maxLength = 0l;
List<List<String>> columnDataList = new ArrayList<>();
for (int i = 0; i < jsonPaths.size(); i++) {
List<String> data = new ArrayList<>();
Object object = JsonPath.read(result, jsonPaths.get(i));
if (object instanceof List && jsonPaths.get(i).contains("[*]")) {
data = (List<String>) object;
}else {
if (StringUtils.isNotEmpty(apiDefinition.getDataPath()) && CollectionUtils.isEmpty(apiDefinition.getJsonFields())) {
List<LinkedHashMap> currentData = new ArrayList<>();
Object object = JsonPath.read(result, apiDefinition.getDataPath());
if (object instanceof List) {
currentData = (List<LinkedHashMap>) object;
} else {
if (object != null) {
data.add(object.toString());
}
currentData.add((LinkedHashMap) object);
}
maxLength = maxLength > data.size() ? maxLength : data.size();
columnDataList.add(data);
}
for (int i = 0; i < maxLength; i++) {
String[] row = new String[apiDefinition.getFields().size()];
dataList.add(row);
}
for (int i = 0; i < columnDataList.size(); i++) {
for (int j = 0; j < columnDataList.get(i).size(); j++) {
dataList.get(j)[i] = Optional.ofNullable(String.valueOf(columnDataList.get(i).get(j))).orElse("").replaceAll("\n", " ").replaceAll("\r", " ");
for (LinkedHashMap data : currentData) {
String[] row = new String[apiDefinition.getFields().size()];
int i = 0;
for (DatasetTableFieldDTO field : apiDefinition.getFields()) {
row[i] = Optional.ofNullable(data.get(field.getOriginName())).orElse("").toString().replaceAll("\n", " ").replaceAll("\r", " ");
i++;
}
dataList.add(row);
}
} else {
List<String> jsonPaths = apiDefinition.getFields().stream().map(DatasetTableFieldDTO::getJsonPath).collect(Collectors.toList());
Long maxLength = 0l;
List<List<String>> columnDataList = new ArrayList<>();
for (int i = 0; i < jsonPaths.size(); i++) {
List<String> data = new ArrayList<>();
Object object = JsonPath.read(result, jsonPaths.get(i));
if (object instanceof List && jsonPaths.get(i).contains("[*]")) {
data = (List<String>) object;
} else {
if (object != null) {
data.add(object.toString());
}
}
maxLength = maxLength > data.size() ? maxLength : data.size();
columnDataList.add(data);
}
for (int i = 0; i < maxLength; i++) {
String[] row = new String[apiDefinition.getFields().size()];
dataList.add(row);
}
for (int i = 0; i < columnDataList.size(); i++) {
for (int j = 0; j < columnDataList.get(i).size(); j++) {
dataList.get(j)[i] = Optional.ofNullable(String.valueOf(columnDataList.get(i).get(j))).orElse("").replaceAll("\n", " ").replaceAll("\r", " ");
}
}
}
}

View File

@ -345,16 +345,6 @@ public class ImpalaQueryProvider extends QueryProvider {
return sqlLimit(st.render(), view);
}
@Override
public String getSQLWithPage(boolean isTable, String table, List<ChartViewFieldDTO> xAxis, List<ChartFieldCustomFilterDTO> fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, PageInfo pageInfo) {
String limit = ((pageInfo.getGoPage() != null && pageInfo.getPageSize() != null) ? " LIMIT " + pageInfo.getPageSize() + " offset " + (pageInfo.getGoPage() - 1) * pageInfo.getPageSize() : "");
if (isTable) {
return originalTableInfo(table, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view) + limit;
} else {
return originalTableInfo("(" + sqlFix(table) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view) + limit;
}
}
private String originalTableInfo(String table, List<ChartViewFieldDTO> xAxis, List<ChartFieldCustomFilterDTO> fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(ImpalaConstants.KEYWORD_TABLE, table))
@ -1297,4 +1287,8 @@ public class ImpalaQueryProvider extends QueryProvider {
"{\"dateformat\": \"yyyyMMdd HH:mm:ss\"}\n" +
"]", Dateformat.class);
}
public String getResultCount(boolean isTable, String sql, List<ChartViewFieldDTO> xAxis, List<ChartFieldCustomFilterDTO> fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) {
return null;
}
}

View File

@ -444,7 +444,7 @@ public class ChartViewService {
fieldMap.put("yAxis", yAxis);
fieldMap.put("extStack", extStack);
fieldMap.put("extBubble", extBubble);
PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view);
PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view, rowPermissionsTree);
String sql = pluginViewSql(pluginViewParam, view);
if (StringUtils.isBlank(sql)) {
return new ArrayList<String[]>();
@ -525,6 +525,9 @@ public class ChartViewService {
datasourceRequest.setQuery(qp.getSQLAsTmp(sql, xAxis, yAxis, fieldCustomFilter, rowPermissionsTree, extFilterList, view));
}
}
List<ChartViewFieldDTO> xAxisForRequest = new ArrayList<>();
xAxisForRequest.addAll(xAxis); xAxisForRequest.addAll(extStack);
datasourceRequest.setXAxis(xAxisForRequest);
data = datasourceProvider.getData(datasourceRequest);
} else if (table.getMode() == 1) {// 抽取
datasourceRequest.setDatasource(ds);
@ -905,7 +908,7 @@ public class ChartViewService {
fieldMap.put("extBubble", extBubble);
fieldMap.put("xAxis", xAxis);
fieldMap.put("yAxis", yAxis);
PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view);
PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view, rowPermissionsTree);
String sql = pluginViewSql(pluginViewParam, view);
if (StringUtils.isBlank(sql)) {
return emptyChartViewDTO(view);
@ -1039,6 +1042,9 @@ public class ChartViewService {
}
datasourceRequest.setQuery(querySql);
List<ChartViewFieldDTO> xAxisForRequest = new ArrayList<>();
xAxisForRequest.addAll(xAxis); xAxisForRequest.addAll(extStack);
datasourceRequest.setXAxis(xAxisForRequest);
data = datasourceProvider.getData(datasourceRequest);
if (CollectionUtils.isNotEmpty(assistFields)) {
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields));
@ -1352,7 +1358,7 @@ public class ChartViewService {
return dto;
}
private PluginViewParam buildPluginParam(Map<String, List<ChartViewFieldDTO>> fieldMap, List<ChartFieldCustomFilterDTO> customFilters, List<ChartExtFilterRequest> extFilters, Datasource ds, DatasetTable table, ChartViewDTO view) {
private PluginViewParam buildPluginParam(Map<String, List<ChartViewFieldDTO>> fieldMap, List<ChartFieldCustomFilterDTO> customFilters, List<ChartExtFilterRequest> extFilters, Datasource ds, DatasetTable table, ChartViewDTO view, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree) {
PluginViewParam pluginViewParam = new PluginViewParam();
PluginViewSetImpl pluginViewSet = BeanUtils.copyBean(new PluginViewSetImpl(), table);
pluginViewSet.setDsType(ds.getType());
@ -1374,6 +1380,7 @@ public class ChartViewService {
pluginViewParam.setPluginChartFieldCustomFilters(fieldFilters);
pluginViewParam.setPluginChartExtFilters(panelFilters);
pluginViewParam.setPluginViewLimit(pluginViewLimit);
pluginViewParam.setRowPermissionsTree(rowPermissionsTree);
return pluginViewParam;
}

View File

@ -15,6 +15,7 @@ import io.dataease.plugins.common.dto.chart.ChartFieldCustomFilterDTO;
import io.dataease.plugins.common.dto.chart.ChartViewFieldDTO;
import io.dataease.plugins.common.dto.sqlObj.SQLObj;
import io.dataease.plugins.common.request.chart.ChartExtFilterRequest;
import io.dataease.plugins.common.request.permission.DataSetRowPermissionsTreeDTO;
import io.dataease.plugins.common.util.BeanUtils;
import io.dataease.plugins.common.util.ConstantsUtil;
import io.dataease.plugins.datasource.query.QueryProvider;
@ -74,9 +75,9 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
String methodName = "transCustomFilterList";
SQLObj sqlObj = BeanUtils.copyBean(SQLObj.builder().build(), pluginViewSQL);
List<ChartFieldCustomFilterDTO> filters = list.stream().map(item -> gson.fromJson(gson.toJson(item), ChartFieldCustomFilterDTO.class)).collect(Collectors.toList());
Object o ;
Object o;
if ((o = execProviderMethod(queryProvider, methodName, sqlObj, filters)) != null) {
return (String)o;
return (String) o;
}
return null;
}
@ -89,30 +90,38 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
List<ChartExtFilterRequest> filters = list.stream().map(item -> gson.fromJson(gson.toJson(item), ChartExtFilterRequest.class)).collect(Collectors.toList());
Object o;
if ((o = execProviderMethod(queryProvider, methodName, sqlObj, filters)) != null) {
return (String)o;
return (String) o;
}
return null;
}
@Override
public String permissionWhere(String s, List<DataSetRowPermissionsTreeDTO> list, PluginViewSQL pluginViewSQL) {
QueryProvider queryProvider = ProviderFactory.getQueryProvider(s);
SQLObj sqlObj = BeanUtils.copyBean(SQLObj.builder().build(), pluginViewSQL);
return queryProvider.transFilterTrees(sqlObj, list);
}
private String sqlFix(String sql) {
if (sql.lastIndexOf(";") == (sql.length() - 1)) {
sql = sql.substring(0, sql.length() - 1);
}
return sql;
}
@Override
public PluginViewSQL getTableObj(PluginViewSet pluginViewSet) {
String tableName = null;
DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(pluginViewSet.getInfo(), DataTableInfoDTO.class);
if (ObjectUtils.isNotEmpty(pluginViewSet.getMode()) && 1 == pluginViewSet.getMode()) {
tableName = TableUtils.tableName(pluginViewSet.getTableId());
}else {
} else {
switch (DatasetType.getEnumObjByKey(pluginViewSet.getType())) {
case DB:
tableName = dataTableInfoDTO.getTable();
break;
case SQL:
String sql = dataTableInfoDTO.isBase64Encryption()? new String(java.util.Base64.getDecoder().decode(dataTableInfoDTO.getSql())): dataTableInfoDTO.getSql();
String sql = dataTableInfoDTO.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfoDTO.getSql())) : dataTableInfoDTO.getSql();
tableName = dataSetTableService.handleVariableDefaultValue(sql, null, pluginViewSet.getDsType());
tableName = "(" + sqlFix(tableName) + ")";
@ -139,7 +148,7 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
PluginViewSQL tableObj = PluginViewSQL.builder().tableName(realTableName).tableAlias(tableAlias).build();
QueryProvider queryProvider = ProviderFactory.getQueryProvider(pluginViewSet.getDsType());
SQLObj sqlObj = SQLObj.builder().tableName(realTableName).tableAlias(tableAlias).build();
PluginViewSetImpl child = (PluginViewSetImpl)pluginViewSet;
PluginViewSetImpl child = (PluginViewSetImpl) pluginViewSet;
queryProvider.setSchema(sqlObj, child.getDs());
tableObj.setTableName(sqlObj.getTableName());
tableObj.setTableAlias(sqlObj.getTableAlias());
@ -149,9 +158,9 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
private String getOriginName(String dsType, PluginViewField pluginViewField, PluginViewSQL tableObj) {
String keyword_fix = ConstantsUtil.constantsValue(dsType, "KEYWORD_FIX");
String originField;
String reflectField = reflectFieldName(dsType, pluginViewField);
String reflectField = reflectFieldName(dsType, pluginViewField);
if (ObjectUtils.isNotEmpty(pluginViewField.getExtField()) && pluginViewField.getExtField() == 2) {
originField = calcFieldRegex(dsType,pluginViewField.getOriginName(), tableObj);
originField = calcFieldRegex(dsType, pluginViewField.getOriginName(), tableObj);
} else if (ObjectUtils.isNotEmpty(pluginViewField.getExtField()) && pluginViewField.getExtField() == 1) {
originField = String.format(keyword_fix, tableObj.getTableAlias(), StringUtils.isNotBlank(reflectField) ? reflectField : pluginViewField.getOriginName());
} else {
@ -164,38 +173,37 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
QueryProvider queryProvider = ProviderFactory.getQueryProvider(dsType);
String methodName = "calcFieldRegex";
SQLObj sqlObj = BeanUtils.copyBean(SQLObj.builder().build(), pluginViewSQL);
Object o ;
Object o;
if ((o = execProviderMethod(queryProvider, methodName, originField, sqlObj)) != null) {
return (String)o;
return (String) o;
}
return null;
}
private String reflectFieldName(String dsType, PluginViewField pluginViewField ) {
private String reflectFieldName(String dsType, PluginViewField pluginViewField) {
QueryProvider queryProvider = ProviderFactory.getQueryProvider(dsType);
String methodName = "reflectFieldName";
DatasetTableField field = BeanUtils.copyBean(new DatasetTableField(), pluginViewField);;
Object o ;
DatasetTableField field = BeanUtils.copyBean(new DatasetTableField(), pluginViewField);
Object o;
if ((o = execProviderMethod(queryProvider, methodName, field)) != null) {
return (String)o;
return (String) o;
}
return null;
}
private PluginViewSQL getField(String dsType, PluginViewField field, String originField, String fieldAlias) {
QueryProvider queryProvider = ProviderFactory.getQueryProvider(dsType);
String methodName;
if (StringUtils.equals(field.getTypeField(), "xAxis") || StringUtils.equals(field.getTypeField(), "extStack")) {
methodName = "getXFields";
}else {
} else {
methodName = "getYFields";
}
ChartViewFieldDTO chartViewFieldDTO = BeanUtils.copyBean(new ChartViewFieldDTO(), field);
Object execResult;
if ((execResult = execProviderMethod(queryProvider, methodName, chartViewFieldDTO, originField, fieldAlias)) != null){
SQLObj sqlObj = (SQLObj)execResult;
if ((execResult = execProviderMethod(queryProvider, methodName, chartViewFieldDTO, originField, fieldAlias)) != null) {
SQLObj sqlObj = (SQLObj) execResult;
PluginViewSQL result = PluginViewSQL.builder().build();
return BeanUtils.copyBean(result, sqlObj);
}
@ -215,27 +223,26 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService {
}
private PluginViewSQL addSort(String sort, String originField, String fieldAlias) {
private PluginViewSQL addSort(String sort, String originField, String fieldAlias) {
if (StringUtils.isNotEmpty(sort) && !StringUtils.equalsIgnoreCase(sort, "none")) {
return PluginViewSQL.builder().orderField(originField).orderAlias(fieldAlias).orderDirection(sort).build();
}
return null;
}
private String getWhere(String dsType, PluginViewField field,String originField,String fieldAlias) {
private String getWhere(String dsType, PluginViewField field, String originField, String fieldAlias) {
QueryProvider queryProvider = ProviderFactory.getQueryProvider(dsType);
String methodName;
if (StringUtils.equals(field.getTypeField(), "xAxis") || StringUtils.equals(field.getTypeField(), "extStack")) {
return null;
}else {
} else {
methodName = "getYWheres";
}
ChartViewFieldDTO chartViewFieldDTO = BeanUtils.copyBean(new ChartViewFieldDTO(), field);
Object execResult;
if ((execResult = execProviderMethod(queryProvider, methodName, chartViewFieldDTO, originField, fieldAlias)) != null){
String where = (String)execResult;
if ((execResult = execProviderMethod(queryProvider, methodName, chartViewFieldDTO, originField, fieldAlias)) != null) {
String where = (String) execResult;
return where;
}
return null;

View File

@ -972,7 +972,11 @@ public class DataSetTableService {
return new ArrayList<>();
}
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(id);
return getSqlVariableDetails(type, Arrays.asList(datasetTable));
if (datasetTable != null) {
return getSqlVariableDetails(type, Arrays.asList(datasetTable));
} else {
return null;
}
}
private List<SqlVariableDetails> getSqlVariableDetails(String type, List<DatasetTable> datasetTables) {
@ -1086,7 +1090,7 @@ public class DataSetTableService {
if (!hasVariables && !tmpSql.contains(SubstitutedParams)) {
return tmpSql;
}
CCJSqlParserUtil.parse(tmpSql, parser -> parser.withSquareBracketQuotation(true));
Statement statement = CCJSqlParserUtil.parse(tmpSql);
Select select = (Select) statement;
@ -2427,7 +2431,7 @@ public class DataSetTableService {
int num = 1;
String line;
while ((line = reader.readLine()) != null) {
if (num > 100) {
if (num > 1000) {
break;
}
data.add(Arrays.asList(line.split(",")));
@ -2861,7 +2865,8 @@ public class DataSetTableService {
hasSubBinaryExpression = false;
try {
BinaryExpression rightBinaryExpression = (BinaryExpression) expr.getRightExpression();
hasSubBinaryExpression = rightBinaryExpression instanceof AndExpression || rightBinaryExpression instanceof OrExpression;;
hasSubBinaryExpression = rightBinaryExpression instanceof AndExpression || rightBinaryExpression instanceof OrExpression;
;
} catch (Exception e) {
}
if (expr.getRightExpression() instanceof BinaryExpression && !hasSubBinaryExpression && hasVariable(expr.getRightExpression().toString())) {

View File

@ -158,11 +158,17 @@ public class DatasourceService {
}
public List<DatasourceDTO> getDatasourceList(DatasourceUnionRequest request) throws Exception {
request.setSort("update_time desc");
List<DatasourceDTO> datasourceDTOS = extDataSourceMapper.queryUnion(request);
datasourceDTOS.forEach(datasourceDTO -> {
datasourceTrans(datasourceDTO);
});
datasourceDTOS.forEach(this::datasourceTrans);
if (StringUtils.isBlank(request.getSort())) {
datasourceDTOS.sort((o1,o2) -> {
int tmp = StringUtils.compareIgnoreCase(o1.getTypeDesc(), o2.getTypeDesc());
if (tmp == 0) {
tmp = StringUtils.compareIgnoreCase(o1.getName(), o2.getName());
}
return tmp;
});
}
return datasourceDTOS;
}

View File

@ -120,6 +120,16 @@ public class PanelAppTemplateService {
}
public void move(PanelAppTemplateRequest request) {
if (!CommonConstants.CHECK_RESULT.NONE.equals(nameCheck(CommonConstants.OPT_TYPE.INSERT, request.getName(), request.getPid(), request.getId()))) {
throw new RuntimeException("当前名称在目标分类中已经存在!请选择其他分类或修改名称");
}
PanelAppTemplateWithBLOBs appTemplate = new PanelAppTemplateWithBLOBs();
appTemplate.setId(request.getId());
appTemplate.setPid(request.getPid());
panelAppTemplateMapper.updateByPrimaryKeySelective(appTemplate);
}
//名称检查
public String nameCheck(String optType, String name, String pid, String id) {
PanelAppTemplateExample example = new PanelAppTemplateExample();

View File

@ -1,3 +1,15 @@
UPDATE `my_plugin`
SET `version` = '1.18.1'
where `plugin_id` > 0 and `version` = '1.18.0';
<<<<<<< HEAD
=======
ALTER TABLE `dataset_table_field`
CHANGE COLUMN `origin_name` `origin_name` LONGTEXT BINARY NOT NULL COMMENT '原始字段名' ;
ALTER TABLE `dataset_table_field`
CHANGE COLUMN `name` `name` LONGTEXT BINARY NOT NULL COMMENT '字段名名' ;
ALTER TABLE `datasource`
CHANGE COLUMN `name` `name` VARCHAR(50) BINARY NOT NULL COMMENT '数据源名称' ;
>>>>>>> dev

View File

@ -0,0 +1,8 @@
UPDATE `my_plugin`
SET `version` = '1.18.2'
where `plugin_id` > 0
and `version` = '1.18.1';
UPDATE `panel_subject`
SET `details` = '{\"width\":1600,\"height\":900,\"scale\":100,\"scaleWidth\":100,\"scaleHeight\":100,\"selfAdaption\":true,\"auxiliaryMatrix\":true,\"openCommonStyle\":true,\"panel\":{\"themeColor\":\"light\",\"color\":\"#F1F3F5\",\"imageUrl\":{},\"backgroundType\":\"color\",\"gap\":\"yes\",\"resultMode\":\"all\",\"resultCount\":1000},\"aidedDesign\":{\"showGrid\":false,\"matrixBase\":4},\"refreshViewLoading\":true,\"refreshUnit\":\"minute\",\"refreshTime\":5,\"themeId\":\"e846db60-9619-11ed-b973-39e0420a3eeb\",\"chartInfo\":{\"chartTitle\":{\"show\":true,\"fontSize\":\"18\",\"color\":\"#000000\",\"hPosition\":\"left\",\"vPosition\":\"top\",\"isItalic\":false,\"isBolder\":true,\"remarkShow\":false,\"remark\":\"\",\"remarkBackgroundColor\":\"#ffffffff\",\"fontFamily\":\"Microsoft YaHei\",\"letterSpace\":\"0\",\"fontShadow\":false},\"chartColor\":{\"value\":\"default\",\"colors\":[\"#5470c6\",\"#91cc75\",\"#fac858\",\"#ee6666\",\"#73c0de\",\"#3ba272\",\"#fc8452\",\"#9a60b4\",\"#ea7ccc\"],\"alpha\":100,\"tableHeaderBgColor\":\"#6D9A49\",\"tableItemBgColor\":\"#FFFFFF\",\"tableHeaderFontColor\":\"#000000\",\"tableFontColor\":\"#000000\",\"tableStripe\":true,\"dimensionColor\":\"#000000\",\"quotaColor\":\"#5470c6\",\"tableBorderColor\":\"#E6E7E4\",\"seriesColors\":[],\"areaBorderColor\":\"#303133\",\"gradient\":false,\"areaBaseColor\":\"#FFFFFF\",\"tableScrollBarColor\":\"rgba(0, 0, 0, 0.15)\",\"tableScrollBarHoverColor\":\"rgba(0, 0, 0, 0.4)\"},\"chartCommonStyle\":{\"backgroundColorSelect\":true,\"color\":\"#FFFFFF\",\"alpha\":100,\"borderRadius\":5,\"innerPadding\":0,\"enable\":false,\"innerImageColor\":\"#1E90FF\",\"backgroundType\":\"outerImage\",\"outerImage\":null},\"filterStyle\":{\"horizontal\":\"left\",\"vertical\":\"top\",\"color\":\"#000000\",\"brColor\":\"\",\"wordColor\":\"\",\"innerBgColor\":\"\"},\"tabStyle\":{\"headFontColor\":\"#OOOOOO\",\"headFontActiveColor\":\"#OOOOOO\",\"headBorderColor\":\"#OOOOOO\",\"headBorderActiveColor\":\"#OOOOOO\",\"headPosition\":\"left\"}}}'
WHERE `id` = 'system_1';

View File

@ -1,6 +1,6 @@
{
"name": "dataease",
"version": "1.18.1",
"version": "1.18.2",
"description": "dataease front",
"private": true,
"scripts": {
@ -51,6 +51,7 @@
"jquery": "^3.1.1",
"js-base64": "^3.7.2",
"js-cookie": "2.2.0",
"js-pinyin": "^0.1.9",
"jsencrypt": "^3.0.0-rc.1",
"jspdf": "^2.3.1",
"jszip": "^3.10.1",

View File

@ -6,7 +6,7 @@
<parent>
<artifactId>dataease-server</artifactId>
<groupId>io.dataease</groupId>
<version>1.18.1</version>
<version>1.18.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -56,3 +56,11 @@ export function nameCheck(data) {
method: 'post'
})
}
export function move(data) {
return request({
url: '/appTemplate/move',
data: data,
method: 'post'
})
}

View File

@ -116,6 +116,13 @@ export function wecomStatus() {
})
}
export function wecomQrParams() {
return request({
url: '/plugin/wecom/getQrParam',
method: 'post'
})
}
export function dingtalkStatus() {
return request({
url: '/api/auth/isOpenDingtalk',

View File

@ -297,6 +297,9 @@ export default {
// this.$emit('handleDrop', e)
// }
handleDrop(e) {
if (!this.dragComponentInfo) {
return
}
this.dragComponentInfo.moveStatus = 'drop'
//
this.dropComponentInfo = deepCopy(this.dragComponentInfo)

View File

@ -24,7 +24,7 @@
>
<el-tooltip :content="item.tooltip">
<span style="float: left;">
<i :class="item.icon" />
<i :class="item.icon"/>
</span>
</el-tooltip>
</el-radio-button>
@ -47,7 +47,7 @@
:value="item.value"
>
<span style="float: left;">
<i :class="item.icon" />
<i :class="item.icon"/>
</span>
<span style="float: right; color: #8492a6; font-size: 12px">{{ item.label }}</span>
</el-option>
@ -257,7 +257,7 @@
@click="goColor"
/>
</el-tooltip>
<div :style="letterDivColor" />
<div :style="letterDivColor"/>
<el-color-picker
ref="colorPicker"
v-model="styleInfo.color"
@ -279,7 +279,7 @@
@click="goBoardColor"
/>
</el-tooltip>
<div :style="boardDivColor" />
<div :style="boardDivColor"/>
<el-color-picker
ref="boardColorPicker"
v-model="styleInfo.borderColor"
@ -302,7 +302,7 @@
@click="goBackgroundColor"
/>
</el-tooltip>
<div :style="backgroundDivColor" />
<div :style="backgroundDivColor"/>
<el-color-picker
ref="backgroundColorPicker"
v-model="styleInfo.backgroundColor"
@ -318,7 +318,7 @@
style="width: 20px;float: left;margin-top: 2px;margin-left: 2px;"
>
<el-tooltip :content="$t('panel.video_info')">
<VideoLinks :link-info="curComponent.videoLinks" />
<VideoLinks :link-info="curComponent.videoLinks"/>
</el-tooltip>
</div>
@ -327,7 +327,7 @@
style="width: 20px;float: left;margin-top: 2px;margin-left: 2px;"
>
<el-tooltip :content="$t('panel.stream_media_info')">
<StreamMediaLinks :link-info="curComponent.streamMediaLinks" />
<StreamMediaLinks :link-info="curComponent.streamMediaLinks"/>
</el-tooltip>
</div>
@ -336,7 +336,7 @@
style="width: 20px;float: left;margin-top: 2px;margin-left: 2px;"
>
<el-tooltip :content="$t('panel.web_addr')">
<FrameLinks :link-info="curComponent.frameLinks" />
<FrameLinks :link-info="curComponent.frameLinks"/>
</el-tooltip>
</div>
<div
@ -356,7 +356,7 @@
style="width: 20px;float: left;margin-top: 2px;margin-left: 10px;"
>
<el-tooltip :content="$t('panel.tab_inner_style')">
<tab-style :style-info="styleInfo" />
<tab-style :style-info="styleInfo"/>
</el-tooltip>
</div>
@ -616,7 +616,7 @@ export default {
mainStyle() {
const style = {
left: (this.getPositionX(this.curComponent.style.left) - this.scrollLeft) + 'px',
left: (this.getPositionX(this.curComponent.style.left) - this.scrollLeft - 10) + 'px',
top: (this.getPositionY(this.curComponent.style.top) - this.scrollTop + 20) + 'px'
}
return style

View File

@ -153,6 +153,30 @@
@change="styleChange"
/>
</el-dropdown-item>
<el-dropdown-item>
<span>
<svg-icon
style="width: 16px; height: 16px;"
icon-class="page-line"
/>
</span>
<el-tooltip
class="item"
:content="$t('panel.export_pdf_page_remark')"
placement="top-start"
>
<span class="text14 margin-left8">{{ $t('panel.export_pdf_page') }}</span>
</el-tooltip>
<el-switch
v-model="showPageLine"
:class="[{['grid-active']: showPageLine},'margin-left8']"
size="mini"
@change="showPageLineChange"
/>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
@ -247,6 +271,7 @@ export default {
},
data() {
return {
showPageLine: false,
showGridSwitch: false,
mobileLayoutInitStatus: false,
isShowPreview: false,
@ -305,6 +330,7 @@ export default {
this.scale = this.canvasStyleData.scale
this.mobileLayoutInitStatus = this.mobileLayoutStatus
this.showGridSwitch = this.canvasStyleData.aidedDesign.showGrid
this.showPageLine = this.canvasStyleData.pdfPageLine?.showPageLine
this.autoCache()
},
beforeDestroy() {
@ -323,6 +349,7 @@ export default {
},
editPanelInit() {
this.showGridSwitch = this.canvasStyleData.aidedDesign.showGrid
this.showPageLine = this.canvasStyleData.pdfPageLine?.showPageLine
},
close() {
//
@ -589,6 +616,10 @@ export default {
this.$store.commit('canvasChange')
this.canvasStyleData.aidedDesign.showGrid = !this.canvasStyleData.aidedDesign.showGrid
},
showPageLineChange() {
this.$store.commit('canvasChange')
this.canvasStyleData.pdfPageLine.showPageLine = !this.canvasStyleData.pdfPageLine.showPageLine
},
// batch option
batchOption() {
bus.$emit('change_panel_right_draw', !this.batchOptStatus)

View File

@ -204,7 +204,7 @@ export default {
return style
},
componentActiveFlag() {
return !this.mobileLayoutStatus && ((this.curComponent && this.config.id === this.curComponent.id && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing'))
return (!this.mobileLayoutStatus || this.terminal === 'mobile') && ((this.curComponent && this.config.id === this.curComponent.id && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing'))
},
scale() {
return Math.min(this.previewCanvasScale.scalePointWidth, this.previewCanvasScale.scalePointHeight)
@ -279,7 +279,7 @@ export default {
} else {
return {
...
getStyle(style, ['top', 'left', 'width', 'height', 'rotate']),
getStyle(style, ['top', 'left', 'width', 'height', 'rotate']),
position: 'relative'
}
}

View File

@ -12,6 +12,11 @@
@mousedown="handleMouseDown"
@scroll="canvasScroll"
>
<page-line-editor
v-if="showPageLine"
ref="main-page-line"
:canvas-style-data="canvasStyleData"
/>
<!-- 网格线 -->
<Grid
v-if="showGrid"
@ -157,6 +162,7 @@ import MarkLine from './MarkLine'
import Area from './Area'
import eventBus from '@/components/canvas/utils/eventBus'
import Grid from './Grid'
import PageLineEditor from './PageLineEditor'
import PGrid from './PGrid'
import { changeStyleWithScale } from '@/components/canvas/utils/translate'
import UserViewDialog from '@/components/canvas/customComponent/UserViewDialog'
@ -763,7 +769,8 @@ export default {
UserViewDialog,
DeOutWidget,
DragShadow,
LinkJumpSet
LinkJumpSet,
PageLineEditor
},
props: {
parentForbid: {
@ -944,11 +951,26 @@ export default {
return false
}
},
showPageLine() {
if (this.canvasStyleData && this.canvasStyleData.pdfPageLine) {
return this.canvasStyleData.pdfPageLine.showPageLine
}
return false
},
editStyle() {
return {
height: this.outStyle.height + this.scrollTop + 'px !important'
}
},
scrollHeight() {
let baseHeight = 0
this.componentData.forEach(item => {
const top = this.getShapeStyleIntDeDrag(item.style, 'top')
const height = this.getShapeStyleIntDeDrag(item.style, 'height')
baseHeight = Math.max(baseHeight, top + height)
})
return baseHeight
},
customStyle() {
let style = {
width: '100%',
@ -1024,6 +1046,19 @@ export default {
},
deep: true
},
scrollHeight: {
handler(newVal, oldVla) {
this.$nextTick(() => {
if (newVal !== oldVla && this.showPageLine) {
const lineRef = this.$refs['main-page-line']
if (lineRef?.init) {
lineRef.init(newVal)
}
}
})
},
deep: true
},
outStyle: {
handler(newVal, oldVla) {
this.resizeParentBoundsRef()
@ -1251,6 +1286,9 @@ export default {
},
changeStyleWithScale,
handleMouseDown(e) {
if (this.isPageLineTarget(e)) {
return
}
// e.preventDefault() drop
if (!this.curComponent || (this.curComponent.component !== 'v-text' && this.curComponent.component !== 'rect-shape')) {
e.preventDefault()
@ -1259,6 +1297,9 @@ export default {
//
this.containerMouseDown(e)
},
isPageLineTarget(e) {
return e.target.classList && [...e.target.classList].includes('page-line-item')
},
hideArea() {
this.isShowArea = 0
@ -1517,6 +1558,9 @@ export default {
}
},
handleDragOver(e) {
if (!this.dragComponentInfo?.shadowStyle) {
return
}
this.dragComponentInfo.shadowStyle.x = e.pageX - 220
this.dragComponentInfo.shadowStyle.y = e.pageY - 90 + this.scrollTop
this.dragComponentInfo.style.left = this.dragComponentInfo.shadowStyle.x / this.scalePointWidth

View File

@ -1,5 +1,5 @@
<template>
<div @mousedown="fieldsAreaDown">
<div @mousedown="fieldsAreaDown" class="field-main">
<el-button
v-for="(field) in fields"
:key="field.id"
@ -29,15 +29,10 @@ export default {
}
},
data() {
return {
}
},
computed: {
},
watch: {
return {}
},
computed: {},
watch: {},
mounted() {
},
methods: {
@ -53,11 +48,18 @@ export default {
</script>
<style scoped>
.field-area{
.field-main {
width: 183px;
max-height: 300px;
overflow-x: hidden;
overflow-y: auto;
}
.field-area {
width: 174px;
margin: 4px 0 0 0;
text-align: left;
margin-left: 0px!important;
margin-left: 0px !important;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View File

@ -0,0 +1,136 @@
<template>
<div class="page-line-container">
<div
v-for="(line, index) in lineLocations"
:key="index"
:ref="baseLineKey + index"
class="page-line-item"
:style="{'top': line + 'px', 'background': panelBg}"
@mousedown="handleMouseDown"
>
<span class="top-span" />
<span class="bottom-span" />
</div>
</div>
</template>
<script>
import { reverseColor } from '@/views/chart/chart/common/common'
export default {
name: 'PageLineEditor',
props: {
canvasStyleData: {
type: Object,
require: true
}
},
data() {
return {
baseLineKey: 'page-line-',
lineLocations: [],
curLineHeight: 0,
clientStartY: 0,
startTop: 0,
movingLineHeight: 0,
scrollHeight: 0,
baseLineColor: '#1F2329'
}
},
computed: {
windowHeight() {
return window.innerHeight - 56
},
panelBg() {
if (this.canvasStyleData.panel.backgroundType === 'color') {
return reverseColor(this.canvasStyleData.panel.color)
}
return this.baseLineColor
},
pdfPageLine() {
return this.$store.state.canvasStyleData.pdfPageLine
}
},
mounted() {
this.$nextTick(() => {
this.init()
})
},
created() {
},
methods: {
resize() {
this.$nextTick(() => {
this.init()
})
},
init(scrollHeight) {
this.lineLocations = []
this.scrollHeight = scrollHeight || document.getElementById('canvas-id-canvas-main').scrollHeight
if (this.pdfPageLine?.proportion) {
this.curLineHeight = this.pdfPageLine.proportion * this.scrollHeight
} else {
this.curLineHeight = this.windowHeight
this.saveLineHeight()
}
let curLineLocation = this.curLineHeight
while (curLineLocation < this.scrollHeight) {
this.lineLocations.push(curLineLocation)
curLineLocation += this.curLineHeight
}
},
handleMouseDown(e) {
this.clientStartY = e.clientY
this.startTop = parseInt(e.target.style.top)
document.onmousemove = ev => this.handleMouseMove(e, ev)
document.onmouseup = () => {
this.curLineHeight = this.movingLineHeight
this.saveLineHeight()
this.init()
document.onmousemove = document.onmouseup = null
}
},
handleMouseMove(e, ev) {
const moveInstance = ev.clientY - this.clientStartY
this.movingLineHeight = this.curLineHeight + moveInstance
e.target.style.top = this.startTop + moveInstance + 'px'
},
saveLineHeight() {
this.$store.commit('canvasChange')
this.canvasStyleData.pdfPageLine.proportion = this.curLineHeight / this.scrollHeight
this.pdfPageLine.proportion = this.curLineHeight / this.scrollHeight
}
}
}
</script>
<style lang="scss" scoped>
.page-line-container {
/* width: 100%;
height: 100%; */
}
.page-line-item {
height: 1px;
width: 100%;
margin: 2px 0;
position: absolute;
z-index: 999;
cursor: row-resize;
span {
width: 20px;
background: #bbb;
left: calc(50% - 5px);
height: 2px;
position: absolute;
}
.top-span {
top: -3px !important;
}
.bottom-span {
top: 3px !important;
}
}
</style>

View File

@ -112,7 +112,7 @@
style="position: absolute;right: 70px;top:15px"
>
<el-button
v-if="showChartInfoType==='enlarge' && showChartInfo && showChartInfo.type !== 'symbol-map'"
v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && showChartInfo.type !== 'symbol-map'"
class="el-icon-picture-outline"
size="mini"
@click="exportViewImg"
@ -120,7 +120,7 @@
{{ $t('chart.export_img') }}
</el-button>
<el-button
v-if="showChartInfoType==='details'"
v-if="showChartInfoType==='details'&& hasDataPermission('export',panelInfo.privileges)"
size="mini"
@click="exportExcel"
>

View File

@ -5,7 +5,7 @@
trigger="click"
@mouseup="handleMouseUp"
>
<slot name="icon" />
<slot name="icon"/>
<el-dropdown-menu v-if="curComponent">
<el-dropdown-item
v-if="editFilter.includes(curComponent.type)"
@ -17,7 +17,8 @@
v-if="curComponent.type != 'custom-button'"
icon="el-icon-document-copy"
@click.native="copy"
><span>{{ $t('panel.copy') }}(<span v-show="systemOS==='Mac'"><i class="icon iconfont icon-command" />+ D</span> <span v-show="systemOS!=='Mac'">Control + D</span>)</span>
><span>{{ $t('panel.copy') }}&nbsp(<span v-show="systemOS==='Mac'"><i class="icon iconfont icon-command"
/>+ D</span> <span v-show="systemOS!=='Mac'">Control + D</span>)</span>
</el-dropdown-item>
<el-dropdown-item
icon="el-icon-delete"
@ -33,7 +34,7 @@
<el-dropdown-item v-if="!curComponent.auxiliaryMatrix">
<el-dropdown placement="right-start">
<span class="el-icon-copy-document">
{{ $t('panel.level') }} <i class="el-icon-arrow-right el-icon--right" />
{{ $t('panel.level') }} <i class="el-icon-arrow-right el-icon--right"/>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
@ -86,15 +87,13 @@
<el-dropdown-item
v-if="curComponent.type != 'custom-button'"
@click.native="hyperlinksSet"
>
<i class="icon iconfont icon-font icon-chaolianjie1" />
{{ $t('panel.hyperlinks') }}
><i class="icon iconfont icon-chaolianjie1"/>{{ $t('panel.hyperlinks') }}
</el-dropdown-item>
<el-dropdown-item
v-if="curComponent.type !== 'view' && !curComponent.auxiliaryMatrix"
@click.native="positionAdjust"
>
<i class="el-icon-map-location" />
<i class="el-icon-map-location"/>
{{ $t('panel.position_adjust') }}
</el-dropdown-item>
</el-dropdown-menu>

View File

@ -32,7 +32,7 @@
v-if="chart.isPlugin"
:ref="element.propValue.id"
:component-name="chart.type + '-view'"
:obj="{chart, trackMenu, searchCount, terminalType: scaleCoefficientType}"
:obj="{active, chart, trackMenu, searchCount, terminalType: scaleCoefficientType}"
:chart="chart"
:track-menu="trackMenu"
:search-count="searchCount"
@ -66,6 +66,7 @@
:terminal-type="scaleCoefficientType"
:scale="scale"
:theme-style="element.commonBackground"
:active="active"
@onChartClick="chartClick"
@onJumpClick="jumpClick"
/>
@ -140,7 +141,7 @@
style="position: absolute;right: 70px;top:15px"
>
<el-button
v-if="showChartInfoType==='enlarge' && showChartInfo && showChartInfo.type !== 'symbol-map'"
v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && showChartInfo.type !== 'symbol-map'"
class="el-icon-picture-outline"
size="mini"
@click="exportViewImg"
@ -148,7 +149,7 @@
{{ $t('chart.export_img') }}
</el-button>
<el-button
v-if="showChartInfoType==='details'"
v-if="showChartInfoType==='details' && hasDataPermission('export',panelInfo.privileges)"
size="mini"
@click="exportExcel"
>
@ -761,6 +762,9 @@ export default {
requestInfo.pageSize = this.currentPage.pageSize
}
}
if (this.isFirstLoad) {
this.element.filters = this.filters?.length ? JSON.parse(JSON.stringify(this.filters)) : []
}
method(id, this.panelInfo.id, requestInfo).then(response => {
// echart
if (response.success) {
@ -1272,6 +1276,7 @@ export default {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.chart-class {

View File

@ -115,8 +115,8 @@ export default {
// 仪表板复制的组件默认不在移动端部署中mobileSelected = false
data.mobileSelected = false
if (!state.curComponent.auxiliaryMatrix) {
data.style.top += 20
data.style.left += 20
data.style.top = Number(data.style.top) + 20
data.style.left = Number(data.style.left) + 20
}
data.id = generateID()
// 如果是用户视图 测先进行底层复制

View File

@ -1,5 +1,7 @@
import store from '@/store'
import eventBus from '@/components/canvas/utils/eventBus'
import { $warning } from '@/utils/message'
import i18n from '@/lang'
const ctrlKey = 17
const commandKey = 91 // mac command
@ -25,6 +27,8 @@ const enlargeKey = 190 // command + .
export const keycodes = [66, 67, 68, 69, 71, 76, 80, 83, 85, 86, 88, 89, 90]
const ignoreComponent = ['de-button', 'de-reset-button']
// 与组件状态无关的操作
const basemap = {
[vKey]: paste,
@ -134,9 +138,13 @@ function decompose() {
function copyAndPast() {
if (store.state.curComponent) {
store.commit('copy')
store.commit('paste', false)
store.commit('recordSnapshot', 'copyAndPast')
if (ignoreComponent.includes(store.state.curComponent.component)) {
$warning(i18n.t('panel.forbidden_copy'))
} else {
store.commit('copy')
store.commit('paste', false)
store.commit('recordSnapshot', 'copyAndPast')
}
}
}

View File

@ -277,8 +277,8 @@ export const THEME_ATTR_TRANS_SLAVE1_BACKGROUND = {
// 移动端特殊属性
export const mobileSpecialProps = {
'lineWidth': 3, // 线宽固定值
'lineSymbolSize': 5// 折点固定值
'lineWidth': 2, // 线宽固定值
'lineSymbolSize': 8// 折点固定值
}
export function getScaleValue(propValue, scale) {

View File

@ -8,7 +8,7 @@ import {
import { ApplicationContext } from '@/utils/ApplicationContext'
import { uuid } from 'vue-uuid'
import store from '@/store'
import { AIDED_DESIGN, MOBILE_SETTING, PANEL_CHART_INFO, TAB_COMMON_STYLE } from '@/views/panel/panel'
import { AIDED_DESIGN, MOBILE_SETTING, PANEL_CHART_INFO, TAB_COMMON_STYLE, PAGE_LINE_DESIGN } from '@/views/panel/panel'
import html2canvas from 'html2canvasde'
export function deepCopy(target) {
@ -83,6 +83,7 @@ export function panelDataPrepare(componentData, componentStyle, callback) {
componentStyle.refreshUnit = (componentStyle.refreshUnit || 'minute')
componentStyle.refreshViewEnable = (componentStyle.refreshViewEnable === undefined ? true : componentStyle.refreshViewEnable)
componentStyle.aidedDesign = (componentStyle.aidedDesign || deepCopy(AIDED_DESIGN))
componentStyle.pdfPageLine = (componentStyle.pdfPageLine || deepCopy(PAGE_LINE_DESIGN))
componentStyle.chartInfo = (componentStyle.chartInfo || deepCopy(PANEL_CHART_INFO))
componentStyle.chartInfo.tabStyle = (componentStyle.chartInfo.tabStyle || deepCopy(TAB_COMMON_STYLE))
componentStyle.themeId = (componentStyle.themeId || 'NO_THEME')

View File

@ -182,8 +182,10 @@ export default {
textAlign: horizontal
}
this.outsideStyle = {
flexWrap: 'wrap'
flexDirection: 'column'
}
if (vertical !== 'top' && this.element.component !== 'de-select-grid') {
this.titleStyle = null
this.outsideStyle = {
@ -192,6 +194,10 @@ export default {
}
}
if (this.element.component === 'de-select-grid') {
this.$set(this.outsideStyle, 'flexDirection', 'column')
}
if (vertical !== 'top' && this.element.component === 'de-number-range') {
if (!this.titleStyle) {
this.titleStyle = {}
@ -255,7 +261,6 @@ export default {
.condition-content-container {
position: relative;
display: table;
width: 100%;
height: 100%;
white-space: nowrap;
@ -263,8 +268,6 @@ export default {
.first-element {
position: relative;
display: table-cell;
vertical-align: middle;
margin: 0px;
padding: 0px;
height: 100%;
@ -292,6 +295,7 @@ export default {
background: #fff;
border: 1px solid #d7dae2;
top: 5px;
height: 100%;
}
.condition-main-line {

View File

@ -455,7 +455,9 @@ export default {
latestMoveY: 0,
seriesIdMap: {
id: ''
}
},
// Tab
ignoreTabMoveComponent: ['de-button', 'de-reset-button', 'de-tabs']
}
},
computed: {
@ -828,6 +830,22 @@ export default {
this.beforeDestroyFunction()
},
methods: {
sizeAdaptor() {
this.top = this.y
this.left = this.x
const [parentWidth, parentHeight] = this.getParentSize()
this.parentWidth = parentWidth
this.parentHeight = parentHeight
const [width, height] = getComputedSize(this.$el)
this.aspectFactor = (this.w !== 'auto' ? this.w : width) / (this.h !== 'auto' ? this.h : height)
if (this.outsideAspectRatio) {
this.aspectFactor = this.outsideAspectRatio
}
this.width = this.w !== 'auto' ? this.w : width
this.height = this.h !== 'auto' ? this.h : height
this.right = this.parentWidth - this.width - this.left
this.bottom = this.parentHeight - this.height - this.top
},
setChartData(chart) {
this.chart = chart
},
@ -1480,6 +1498,7 @@ export default {
this.hasMove && this.$store.commit('recordSnapshot', 'handleUp')
// snapshot false
this.hasMove = false
this.sizeAdaptor()
}, 200)
} else {
this.hasMove && this.$store.commit('recordSnapshot', 'handleUp')
@ -1888,18 +1907,7 @@ export default {
if (!this.enableNativeDrag) {
this.$el.ondragstart = () => false
}
const [parentWidth, parentHeight] = this.getParentSize()
this.parentWidth = parentWidth
this.parentHeight = parentHeight
const [width, height] = getComputedSize(this.$el)
this.aspectFactor = (this.w !== 'auto' ? this.w : width) / (this.h !== 'auto' ? this.h : height)
if (this.outsideAspectRatio) {
this.aspectFactor = this.outsideAspectRatio
}
this.width = this.w !== 'auto' ? this.w : width
this.height = this.h !== 'auto' ? this.h : height
this.right = this.parentWidth - this.width - this.left
this.bottom = this.parentHeight - this.height - this.top
this.sizeAdaptor()
// data-*
this.settingAttribute()
@ -1966,7 +1974,7 @@ export default {
const width = this.width
const height = this.height
// tab tabtab
if (this.isTabMoveCheck && this.element.type !== 'de-tabs') {
if (this.isTabMoveCheck && !this.ignoreTabMoveComponent.includes(this.element.component)) {
const nodes = this.$el.parentNode.childNodes //
for (const item of nodes) {
if (

View File

@ -157,6 +157,7 @@ export default {
this.element.options.attrs.fieldId.length > 0 &&
method(param).then(res => {
this.data = this.optionData(res.data)
this.clearDefault(this.data)
bus.$emit('valid-values-change', true)
}).catch(e => {
bus.$emit('valid-values-change', false)
@ -228,6 +229,27 @@ export default {
bus.$off('reset-default-value', this.resetDefaultValue)
},
methods: {
clearDefault(optionList) {
const emptyOption = !optionList?.length
if (!this.inDraw && this.element.options.value) {
if (Array.isArray(this.element.options.value)) {
if (emptyOption) {
this.element.options.value = []
return
}
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item))
} else {
if (emptyOption) {
this.element.options.value = ''
return
}
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value.split(',')))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item)).join(',')
}
}
},
clearHandler() {
this.value = this.element.options.attrs.multiple ? [] : null
this.$refs.deSelect && this.$refs.deSelect.resetSelectAll && this.$refs.deSelect.resetSelectAll()

View File

@ -179,6 +179,7 @@ export default {
this.element.options.attrs.fieldId.length > 0 &&
method(param).then(res => {
this.data = this.optionData(res.data)
this.clearDefault(this.data)
this.changeInputStyle()
if (this.element.options.attrs.multiple) {
this.checkAll = this.value.length === this.data.length
@ -250,6 +251,27 @@ export default {
bus.$off('reset-default-value', this.resetDefaultValue)
},
methods: {
clearDefault(optionList) {
const emptyOption = !optionList?.length
if (!this.inDraw && this.element.options.value) {
if (Array.isArray(this.element.options.value)) {
if (emptyOption) {
this.element.options.value = []
return
}
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item))
} else {
if (emptyOption) {
this.element.options.value = ''
return
}
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value.split(',')))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item)).join(',')
}
}
},
clearHandler() {
this.value = this.element.options.attrs.multiple ? [] : null
this.checkAll = false

View File

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.16428 9.00002H18.8354C19.1103 9.00002 19.3332 9.22388 19.3332 9.50002V10.5C19.3332 10.7762 19.1103 11 18.8354 11H1.16428C0.889367 11 0.666504 10.7762 0.666504 10.5V9.50002C0.666504 9.22388 0.889367 9.00002 1.16428 9.00002ZM1.16428 0.666687H4.16452C4.43943 0.666687 4.66229 0.890545 4.66229 1.16669V2.16669C4.66229 2.44283 4.43943 2.66669 4.16452 2.66669H1.16428C0.889367 2.66669 0.666504 2.44283 0.666504 2.16669V1.16669C0.666504 0.890545 0.889367 0.666687 1.16428 0.666687ZM8.50118 0.666687H11.5014C11.7763 0.666687 11.9992 0.890545 11.9992 1.16669V2.16669C11.9992 2.44283 11.7763 2.66669 11.5014 2.66669H8.50118C8.22626 2.66669 8.0034 2.44283 8.0034 2.16669V1.16669C8.0034 0.890545 8.22626 0.666687 8.50118 0.666687ZM15.8309 0.666687H18.8312C19.1061 0.666687 19.329 0.890545 19.329 1.16669V2.16669C19.329 2.44283 19.1061 2.66669 18.8312 2.66669H15.8309C15.556 2.66669 15.3332 2.44283 15.3332 2.16669V1.16669C15.3332 0.890545 15.556 0.666687 15.8309 0.666687ZM1.16428 17.3348H4.16452C4.43943 17.3348 4.66229 17.5587 4.66229 17.8348V18.8348C4.66229 19.111 4.43943 19.3348 4.16452 19.3348H1.16428C0.889367 19.3348 0.666504 19.111 0.666504 18.8348V17.8348C0.666504 17.5587 0.889367 17.3348 1.16428 17.3348ZM8.50118 17.3348H11.5014C11.7763 17.3348 11.9992 17.5587 11.9992 17.8348V18.8348C11.9992 19.111 11.7763 19.3348 11.5014 19.3348H8.50118C8.22626 19.3348 8.0034 19.111 8.0034 18.8348V17.8348C8.0034 17.5587 8.22626 17.3348 8.50118 17.3348ZM15.8309 17.3348H18.8312C19.1061 17.3348 19.329 17.5587 19.329 17.8348V18.8348C19.329 19.111 19.1061 19.3348 18.8312 19.3348H15.8309C15.556 19.3348 15.3332 19.111 15.3332 18.8348V17.8348C15.3332 17.5587 15.556 17.3348 15.8309 17.3348Z" fill="#1F2329"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1509,7 +1509,14 @@ export default {
Line (area) chart, Column (Bar) chart, Dashboard: {a} is series name, {b} is category value, {c} is value<br>
Pie chart, Funnel chart: {a} is series name, {b} is data item name, {c} is value, {d} is percentage<br>
Map : {a} (series name), {b} is area name, {c} is merged values, {d} is none<br>
Scatter (Bubble) plot: {a} is series name, {b} is data name, {c} is numeric array, {d} is none`
Scatter (Bubble) plot: {a} is series name, {b} is data name, {c} is numeric array, {d} is none`,
h_position: 'Horizontal Position',
v_position: 'Vertical Position',
p_left: 'Left',
p_right: 'Right',
p_top: 'Top',
p_bottom: 'Bottom',
p_center: 'Center'
},
dataset: {
spend_time: 'Spend',
@ -1877,6 +1884,7 @@ export default {
all_compute_mode: 'Direct connection and extraction mode',
extra_params: 'Extra JDBC connection string',
please_input_dataPath: 'Please enter the JsonPath data path',
show_api_data: 'View API raw data',
warning: 'Contains invalid table',
data_table: 'Dataset Table',
data_table_name: 'Dataset Table name',
@ -1887,7 +1895,9 @@ export default {
base_info: 'Basic information',
column_info: 'Data structure',
request: 'Request',
isUseJsonPath: 'Specify JsonPath or not',
path_all_info: 'Please fill in the full address',
jsonpath_info: 'Please fill in JsonPath',
req_param: 'Request parameters',
headers: 'Request header',
key: 'Key',
@ -1956,6 +1966,7 @@ export default {
back_parent: 'Back to previous'
},
panel: {
forbidden_copy: 'Forbidden copy',
url_check_error: 'Jump error, Illegal URL',
view_style: 'View Style',
view_color_setting: 'View Color Setting',
@ -2244,6 +2255,8 @@ export default {
aided_grid: 'Aided Grid',
aided_grid_open: 'Open',
aided_grid_close: 'Close',
export_pdf_page: 'Pagination Line',
export_pdf_page_remark: 'Only valid for API export dashboard PDF pagination',
subject_no_edit: 'System Subject Can Not Edit',
subject_name_not_null: 'Subject Name Can Not Be Null And Less Than 20 charts',
is_enable: 'Enable',
@ -2426,7 +2439,9 @@ export default {
standard: 'Standard',
enterprise: 'Enterprise',
support: 'Get technical support',
update_success: 'Update Success'
update_success: 'Update Success',
serial_no: 'Serial Number',
remark: 'Remark'
},
template: {
exit_same_template_check: 'The Same Name Exists In Now Class. Do You Want To Override It?',
@ -2787,6 +2802,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': 'Template file error',
'i18n_max_user_import_size': 'File size exceeds 10M',
app_template: {
move: 'Move',
move_item: 'Move App',
datasource_new: 'New',
datasource_history: 'Multiplexing',
datasource_from: 'Datasource From',
@ -2826,9 +2843,9 @@ export default {
},
watermark: {
support_params: 'Currently supported parameters:',
enable: 'Enable',
enable: 'Watermark Enable',
enable_panel_custom: 'Allow the dashboard to open or close the watermark independently',
content: 'content',
content: 'Watermark Content',
custom_content: 'Custom Content',
account: 'Account',
nick_name: 'Nick Name',
@ -2837,8 +2854,8 @@ export default {
watermark_color: 'Watermark Color',
watermark_font_size: 'Watermark Fontsize',
watermark_space: 'Watermark Space',
horizontal: 'Horizontal',
vertical: 'Vertical',
horizontal: 'Horizontal Space',
vertical: 'Vertical Space',
reset: 'Reset',
preview: 'Preview',
save: 'Save'

View File

@ -1503,7 +1503,14 @@ export default {
折線區域柱狀條形儀表盤 : {a}系列名稱{b}類目值{c}數值<br>
餅圖漏鬥圖: {a}系列名稱{b}數據項名稱{c}數值, {d}百分比<br>
地圖 : {a}系列名稱{b}區域名稱{c}合並數值, {d}<br>
散點圖氣泡 : {a}系列名稱{b}數據名稱{c}數值數組, {d}`
散點圖氣泡 : {a}系列名稱{b}數據名稱{c}數值數組, {d}`,
h_position: '水平位置',
v_position: '垂直位置',
p_left: '左對齊',
p_right: '右對齊',
p_top: '上對齊',
p_bottom: '下對齊',
p_center: '居中'
},
dataset: {
spend_time: '耗時',
@ -1871,6 +1878,7 @@ export default {
all_compute_mode: '直連、抽取模式',
extra_params: '額外的JDBC連接字符串',
please_input_dataPath: '請輸入 JsonPath 數據路徑',
show_api_data: '查看API原始數據',
warning: '包含無效數據表',
data_table: '數據表',
data_table_name: '數據表名稱',
@ -1881,7 +1889,9 @@ export default {
base_info: '基礎信息',
column_info: '資料結構',
request: '請求',
isUseJsonPath: '是否指定JsonPath',
path_all_info: '請輸入完整地址',
jsonpath_info: '請輸入JsonPath',
req_param: '請求參數',
headers: '請求頭',
key: '鍵',
@ -1950,6 +1960,7 @@ export default {
back_parent: '返回上一級'
},
panel: {
forbidden_copy: '當前組件不允許復製',
url_check_error: '跳轉錯誤URL不合法',
view_style: '視圖樣式',
view_color_setting: '視圖配色',
@ -2238,6 +2249,8 @@ export default {
aided_grid: '輔助設計網格',
aided_grid_open: '打開',
aided_grid_close: '關閉',
export_pdf_page: '分頁線',
export_pdf_page_remark: '僅對API導出儀表板PDF分頁有效',
subject_no_edit: '繫統主題不能修改',
subject_name_not_null: '主題名稱需要1~20字符',
is_enable: '是否啟用',
@ -2420,7 +2433,9 @@ export default {
standard: '標準版',
enterprise: '企業版',
support: '獲取技術支持',
update_success: '更新成功'
update_success: '更新成功',
serial_no: '序列號',
remark: '備註'
},
template: {
exit_same_template_check: '當前分類存在相同名稱模闆,是否覆蓋?',
@ -2781,6 +2796,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版錯誤',
'i18n_max_user_import_size': '文件最大不能超過10M',
app_template: {
move: '移動',
move_item: '移動應用',
datasource_new: '新建',
datasource_history: '復用',
datasource_from: '數據來源',
@ -2819,9 +2836,9 @@ export default {
},
watermark: {
support_params: '當前支持的參數:',
enable: '啟用',
enable: '啟用水印',
enable_panel_custom: '允許儀表板單獨打開或者關閉水印',
content: '內容',
content: '水印內容',
custom_content: '自定義公式',
account: '賬號',
nick_name: '昵稱',
@ -2830,8 +2847,8 @@ export default {
watermark_color: '水印顏色',
watermark_font_size: '水印字號',
watermark_space: '水印間距',
horizontal: '橫向',
vertical: '縱向',
horizontal: '橫向間距',
vertical: '縱向間距',
reset: '重置',
preview: '預覽',
save: '保存'

View File

@ -1502,7 +1502,14 @@ export default {
折线区域柱状条形仪表盘 : {a}系列名称{b}类目值{c}数值<br>
饼图漏斗图: {a}系列名称{b}数据项名称{c}数值, {d}百分比<br>
地图 : {a}系列名称{b}区域名称{c}合并数值, {d}<br>
散点图气泡 : {a}系列名称{b}数据名称{c}数值数组, {d}`
散点图气泡 : {a}系列名称{b}数据名称{c}数值数组, {d}`,
h_position: '水平位置',
v_position: '垂直位置',
p_left: '左对齐',
p_right: '右对齐',
p_top: '上对齐',
p_bottom: '下对齐',
p_center: '居中'
},
dataset: {
spend_time: '耗时',
@ -1870,6 +1877,7 @@ export default {
all_compute_mode: '直连、抽取模式',
extra_params: '额外的JDBC连接字符串',
please_input_dataPath: '请输入 JsonPath 数据路径',
show_api_data: '查看API原始数据',
warning: '包含无效数据表',
data_table: '数据表',
data_table_name: '数据表名称',
@ -1880,7 +1888,9 @@ export default {
base_info: '基础信息',
column_info: '数据结构',
request: '请求',
isUseJsonPath: '是否指定JsonPath',
path_all_info: '请填入完整地址',
jsonpath_info: '请填入JsonPath',
req_param: '请求参数',
headers: '请求头',
key: '键',
@ -1950,6 +1960,7 @@ export default {
back_parent: '返回上一级'
},
panel: {
forbidden_copy: '当前组件不允许复制',
url_check_error: '跳转错误URL不合法',
view_style: '视图样式',
view_color_setting: '视图配色',
@ -2238,6 +2249,8 @@ export default {
aided_grid: '辅助设计网格',
aided_grid_open: '打开',
aided_grid_close: '关闭',
export_pdf_page: '分页线',
export_pdf_page_remark: '仅对API导出仪表板PDF分页有效',
subject_no_edit: '系统主题不能修改',
subject_name_not_null: '主题名称需要1~20字符',
is_enable: '是否启用',
@ -2420,7 +2433,9 @@ export default {
standard: '标准版',
enterprise: '企业版',
support: '获取技术支持',
update_success: '更新成功'
update_success: '更新成功',
serial_no: '序列号',
remark: '备注'
},
template: {
exit_same_template_check: '当前分类存在相同名称模板,是否覆盖?',
@ -2781,6 +2796,8 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版错误',
'i18n_max_user_import_size': '文件最大不能超过10M',
app_template: {
move: '移动',
move_item: '移动应用',
datasource_new: '新建',
datasource_history: '复用',
datasource_from: '数据来源',
@ -2819,9 +2836,9 @@ export default {
},
watermark: {
support_params: '当前支持的参数:',
enable: '启用',
enable: '启用水印',
enable_panel_custom: '允许仪表板单独打开或者关闭水印',
content: '内容',
content: '水印内容',
custom_content: '自定义公式',
account: '账号',
nick_name: '昵称',
@ -2830,8 +2847,8 @@ export default {
watermark_color: '水印颜色',
watermark_font_size: '水印字号',
watermark_space: '水印间距',
horizontal: '横向',
vertical: '纵向',
horizontal: '横向间距',
vertical: '纵向间距',
reset: '重置',
preview: '预览',
save: '保存'

View File

@ -1721,3 +1721,34 @@ div:focus {
display: inline-block;
}
}
.operator-bar {
width: 100%;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
background: #fff;
top: 0;
z-index: 15;
.title {
font-family: PingFang SC;
font-size: 16px;
font-weight: 500;
line-height: 24px;
color: #1f2329;
}
}
.el-table-column--selection {
.cell {
padding: 0 14px !important;
}
}
.dept-popper {
.el-tree-node__label {
color: var(--deTextPrimary, #1F2329) !important;
}
}

View File

@ -23,6 +23,15 @@
component-name="LKSWithoutLogin"
/>
<plugin-com
v-else-if="isWecomLink && wecomOpen"
ref="WecomWithoutLogin"
:app-id="appId"
:agent-id="agentId"
:redirect-uri="redirectUri"
component-name="WecomWithoutLogin"
/>
<div
v-if="isDingTalkLink && !loading && !dingtalkOpen"
class="auto-login-missing"
@ -58,12 +67,33 @@
<span>未开启国际飞书</span>
</div>
<div
v-if="isWecomLink && !loading && !wecomOpen"
class="auto-login-missing"
>
<span>未开启企业微信</span>
</div>
<div
v-if="isWecomLink && !loading && !appId"
class="auto-login-missing"
>
<span>缺失企业ID</span>
</div>
<div
v-if="isWecomLink && !loading && !agentId"
class="auto-login-missing"
>
<span>缺失应用ID</span>
</div>
</div>
</template>
<script>
import PluginCom from '@/views/system/plugin/PluginCom'
import { dingtalkStatus, larkStatus, larksuiteStatus, larkAppId } from '@/api/user'
import { dingtalkStatus, larkStatus, larksuiteStatus, larkAppId, wecomStatus, wecomQrParams } from '@/api/user'
export default {
name: 'DeAutoLogin',
components: { PluginCom },
@ -75,7 +105,10 @@ export default {
dingtalkOpen: false,
larkOpen: false,
larksuiteOpen: false,
loading: true
loading: true,
wecomOpen: false,
agentId: null,
redirectUri: null
}
},
computed: {
@ -87,6 +120,9 @@ export default {
},
isLarksuiteLink() {
return this.type === 'larksuite'
},
isWecomLink() {
return this.type === 'wecom'
}
},
created() {
@ -124,6 +160,20 @@ export default {
}).catch(e => {
this.loading = false
})
this.isWecomLink && wecomStatus().then(res => {
if (res.success && res.data) {
wecomQrParams().then(resp => {
this.appId = resp.data.appid
this.agentId = resp.data.agentid
this.redirectUri = resp.data.redirectUri
this.wecomOpen = true
this.loading = false
})
}
}).catch(e => {
this.loading = false
})
},
methods: {

View File

@ -127,7 +127,9 @@ export const DEFAULT_SIZE = {
symbolOpacity: 0.7,
symbolStrokeWidth: 2,
showIndex: false,
indexLabel: '序号'
indexLabel: '序号',
hPosition: 'center',
vPosition: 'center'
}
export const DEFAULT_SUSPENSION = {
show: true
@ -507,12 +509,14 @@ export const BASE_BAR = {
},
{
type: 'inside',
disabled: true,
xAxisIndex: [0],
start: 0,
end: 100
},
{
type: 'inside',
disabled: true,
yAxisIndex: [0],
start: 0,
end: 100
@ -563,12 +567,14 @@ export const HORIZONTAL_BAR = {
},
{
type: 'inside',
disabled: true,
xAxisIndex: [0],
start: 0,
end: 100
},
{
type: 'inside',
disabled: true,
yAxisIndex: [0],
start: 0,
end: 100
@ -621,12 +627,14 @@ export const BASE_LINE = {
},
{
type: 'inside',
disabled: true,
xAxisIndex: [0],
start: 0,
end: 100
},
{
type: 'inside',
disabled: true,
yAxisIndex: [0],
start: 0,
end: 100
@ -903,14 +911,10 @@ export const BASE_MAP = {
},
geo: {
map: 'MAP',
roam: true,
nameMap: {
},
roam: false,
nameMap: {},
itemStyle: {
normal: {
},
normal: {},
emphasis: {
label: {
show: false
@ -926,9 +930,7 @@ export const BASE_MAP = {
roam: true,
data: [],
itemStyle: {
normal: {
},
normal: {},
emphasis: {
label: {
show: false
@ -984,12 +986,14 @@ export const BASE_SCATTER = {
},
{
type: 'inside',
disabled: true,
xAxisIndex: [0],
start: 0,
end: 100
},
{
type: 'inside',
disabled: true,
yAxisIndex: [0],
start: 0,
end: 100
@ -1019,6 +1023,7 @@ export const BASE_TREEMAP = {
{
// name: '',
type: 'treemap',
roam: true,
itemStyle: {
gapWidth: 2
},
@ -1079,12 +1084,14 @@ export const BASE_MIX = {
},
{
type: 'inside',
disabled: true,
xAxisIndex: [0],
start: 0,
end: 100
},
{
type: 'inside',
disabled: true,
yAxisIndex: [0],
start: 0,
end: 100
@ -1132,6 +1139,6 @@ export const CHART_FONT_LETTER_SPACE = [
{ name: '10px', value: '10' }
]
export const NOT_SUPPORT_PAGE_DATASET = ['kylin', 'sqlServer', 'es', 'presto', 'ds_doris', 'StarRocks']
export const NOT_SUPPORT_PAGE_DATASET = ['kylin', 'sqlServer', 'es', 'presto', 'ds_doris', 'StarRocks', 'impala']
export const SUPPORT_Y_M = ['y', 'y_M', 'y_M_d']

View File

@ -352,7 +352,7 @@ export function seniorCfg(chart_option, chart) {
label: {
show: true,
color: ele.color,
fontSize: 10,
fontSize: ele.fontSize ? parseInt(ele.fontSize) : 10,
position: xAxis.position === 'bottom' ? 'insideStartTop' : 'insideEndTop',
formatter: function(param) {
return ele.name + ' : ' + valueFormatter(param.value, axisFormatterCfg)
@ -374,7 +374,7 @@ export function seniorCfg(chart_option, chart) {
label: {
show: true,
color: ele.color,
fontSize: 10,
fontSize: ele.fontSize ? parseInt(ele.fontSize) : 10,
position: yAxis.position === 'left' ? 'insideStartTop' : 'insideEndTop',
formatter: function(param) {
return ele.name + ' : ' + valueFormatter(param.value, axisFormatterCfg)

View File

@ -850,7 +850,7 @@ export function getAnalyse(chart) {
style: {
textBaseline: 'bottom',
fill: ele.color,
fontSize: 10
fontSize: ele.fontSize ? parseInt(ele.fontSize) : 10
}
})
} else {
@ -864,7 +864,7 @@ export function getAnalyse(chart) {
style: {
textBaseline: 'bottom',
fill: ele.color,
fontSize: 10
fontSize: ele.fontSize ? parseInt(ele.fontSize) : 10
}
})
}

View File

@ -206,7 +206,9 @@ export const TYPE_CONFIGS = [
'dimensionFontStyle',
'dimensionLetterSpace',
'dimensionFontShadow',
'spaceSplit'
'spaceSplit',
'hPosition',
'vPosition'
],
'title-selector-ant-v': [
'show',
@ -251,7 +253,9 @@ export const TYPE_CONFIGS = [
'dimensionFontStyle',
'dimensionLetterSpace',
'dimensionFontShadow',
'spaceSplit'
'spaceSplit',
'hPosition',
'vPosition'
],
'title-selector-ant-v': [
'show',
@ -1939,7 +1943,9 @@ export const TYPE_CONFIGS = [
'dimensionFontStyle',
'dimensionLetterSpace',
'dimensionFontShadow',
'spaceSplit'
'spaceSplit',
'hPosition',
'vPosition'
],
'title-selector': [
'show',
@ -1984,7 +1990,9 @@ export const TYPE_CONFIGS = [
'dimensionFontStyle',
'dimensionLetterSpace',
'dimensionFontShadow',
'spaceSplit'
'spaceSplit',
'hPosition',
'vPosition'
],
'title-selector': [
'show',

View File

@ -65,6 +65,11 @@ export default {
MapController
},
props: {
active: {
type: Boolean,
required: false,
default: false
},
chart: {
type: Object,
required: true
@ -121,7 +126,19 @@ export default {
buttonTextColor: null,
loading: true,
showSuspension: true,
currentSeriesId: null
currentSeriesId: null,
haveScrollType: [
'treemap',
'map',
'chart-mix',
'bar',
'bar-stack',
'bar-horizontal',
'bar-stack-horizontal',
'line',
'line-stack',
'scatter'
]
}
},
@ -134,6 +151,11 @@ export default {
])
},
watch: {
active: {
handler(newVal, oldVla) {
this.scrollStatusChange(newVal)
}
},
currentSeriesId(value, old) {
if (value !== old) {
this.preDraw()
@ -173,6 +195,39 @@ export default {
this.loadThemeStyle()
},
methods: {
scrollStatusChange() {
if (this.haveScrollType.includes(this.chart.type)) {
const opt = this.myChart.getOption()
this.adaptorOpt(opt)
if (this.chart.type === 'treemap') {
this.myChart.dispose()
this.myChart = null
this.preDraw()
} else {
this.myChart.setOption(opt)
}
}
},
adaptorOpt(opt) {
const disabledStatus = !this.active
if (opt.dataZoom) {
opt.dataZoom.forEach(function(s) {
if (s.type === 'inside') {
s.disabled = disabledStatus
}
})
}
if (opt.geo) {
if (opt.geo instanceof Array) {
opt.geo[0].roam = this.active
} else {
opt.geo.roam = this.active
}
}
if (this.chart.type === 'treemap' && opt.series) {
opt.series[0].roam = this.active
}
},
changeSeriesId(param) {
const { id, seriesId } = param
if (id !== this.chart.id) {
@ -356,8 +411,10 @@ export default {
},
initMapChart(geoJson, chart, curAreaCode) {
this.formatGeoJson(geoJson)
this.$echarts.registerMap('MAP', geoJson)
const mapId = 'MAP' + this.chartId
this.$echarts.registerMap(mapId, geoJson)
const base_json = JSON.parse(JSON.stringify(BASE_MAP))
base_json.geo.map = mapId
let themeStyle = null
if (this.themeStyle) {
themeStyle = JSON.parse(JSON.stringify(this.themeStyle))
@ -391,6 +448,7 @@ export default {
}
},
myEcharts(option) {
this.adaptorOpt(option)
//
const chart = this.myChart
this.setBackGroundBorder()

View File

@ -189,6 +189,9 @@ export default {
this.label_content_class.letterSpacing = (customAttr.size.quotaLetterSpace ? customAttr.size.quotaLetterSpace : DEFAULT_SIZE.quotaLetterSpace) + 'px'
this.label_content_class.textShadow = customAttr.size.quotaFontShadow ? '2px 2px 4px' : 'none'
this.content_class.alignItems = customAttr.size.hPosition ? customAttr.size.hPosition : DEFAULT_SIZE.hPosition
this.content_class.justifyContent = customAttr.size.vPosition ? customAttr.size.vPosition : DEFAULT_SIZE.vPosition
if (!this.dimensionShow) {
this.label_space.marginTop = '0px'
} else {

View File

@ -216,6 +216,9 @@ export default {
this.label_content_class.letterSpacing = (customAttr.size.quotaLetterSpace ? customAttr.size.quotaLetterSpace : DEFAULT_SIZE.quotaLetterSpace) + 'px'
this.label_content_class.textShadow = customAttr.size.quotaFontShadow ? '2px 2px 4px' : 'none'
this.content_class.alignItems = customAttr.size.hPosition ? customAttr.size.hPosition : DEFAULT_SIZE.hPosition
this.content_class.justifyContent = customAttr.size.vPosition ? customAttr.size.vPosition : DEFAULT_SIZE.vPosition
if (!this.dimensionShow) {
this.label_space.marginTop = '0px'
} else {

View File

@ -121,6 +121,11 @@ export default {
senior = JSON.parse(chart.senior)
}
if (senior.assistLine) {
for (let i = 0; i < senior.assistLine.length; i++) {
if (!senior.assistLine[i].fontSize) {
senior.assistLine[i].fontSize = '10'
}
}
this.assistLine = senior.assistLine
} else {
this.assistLine = []

View File

@ -41,7 +41,7 @@
</el-col>
<el-col
v-if="item.field === '0'"
:span="8"
:span="6"
>
<el-input
v-model="item.value"
@ -54,7 +54,7 @@
</el-col>
<el-col
v-if="item.field === '1'"
:span="8"
:span="6"
>
<el-select
v-model="item.fieldId"
@ -119,7 +119,24 @@
/>
</el-select>
</el-col>
<el-col :span="4">
<el-col :span="3">
<el-select
v-model="item.fontSize"
size="mini"
class="select-item"
style="margin-left: 10px;"
:placeholder="$t('chart.text_fontsize')"
@change="changeAssistLine"
>
<el-option
v-for="option in fontSize"
:key="option.value"
:label="option.name"
:value="option.value"
/>
</el-select>
</el-col>
<el-col :span="3">
<el-select
v-model="item.lineType"
size="mini"
@ -135,7 +152,7 @@
</el-select>
</el-col>
<el-col
:span="2"
:span="1"
style="text-align: center;"
>
<el-color-picker
@ -145,7 +162,7 @@
@change="changeAssistLine"
/>
</el-col>
<el-col :span="2">
<el-col :span="1">
<el-button
type="text"
icon="el-icon-delete"
@ -186,7 +203,8 @@ export default {
value: '0',
lineType: 'solid',
color: '#ff0000',
curField: {}
curField: {},
fontSize: '10'
},
fieldOptions: [
{ label: this.$t('chart.field_fixed'), value: '0' },
@ -198,7 +216,8 @@ export default {
{ label: this.$t('chart.line_type_dotted'), value: 'dotted' }
],
predefineColors: COLOR_PANEL,
quotaData: []
quotaData: [],
fontSize: []
}
},
watch: {
@ -216,6 +235,15 @@ export default {
},
init() {
this.lineArr = JSON.parse(JSON.stringify(this.line))
const arr = []
for (let i = 10; i <= 60; i = i + 2) {
arr.push({
name: i + '',
value: i + ''
})
}
this.fontSize = arr
},
addLine() {
const obj = { ...this.lineObj,

View File

@ -634,6 +634,54 @@
@change="changeBarSizeCase('spaceSplit')"
/>
</el-form-item>
<el-form-item
v-show="showProperty('hPosition')"
:label="$t('chart.h_position')"
class="form-item"
>
<el-select
v-model="sizeForm.hPosition"
:placeholder="$t('chart.h_position')"
@change="changeBarSizeCase('hPosition')"
>
<el-option
value="start"
:label="$t('chart.p_left')"
>{{ $t('chart.p_left') }}</el-option>
<el-option
value="center"
:label="$t('chart.p_center')"
>{{ $t('chart.p_center') }}</el-option>
<el-option
value="end"
:label="$t('chart.p_right')"
>{{ $t('chart.p_right') }}</el-option>
</el-select>
</el-form-item>
<el-form-item
v-show="showProperty('vPosition')"
:label="$t('chart.v_position')"
class="form-item"
>
<el-select
v-model="sizeForm.vPosition"
:placeholder="$t('chart.v_position')"
@change="changeBarSizeCase('vPosition')"
>
<el-option
value="start"
:label="$t('chart.p_top')"
>{{ $t('chart.p_top') }}</el-option>
<el-option
value="center"
:label="$t('chart.p_center')"
>{{ $t('chart.p_center') }}</el-option>
<el-option
value="end"
:label="$t('chart.p_bottom')"
>{{ $t('chart.p_bottom') }}</el-option>
</el-select>
</el-form-item>
</div>
<!--text&label-end-->
<!--scatter-begin-->
@ -1076,6 +1124,9 @@ export default {
this.sizeForm.dimensionFontIsItalic = this.sizeForm.dimensionFontIsItalic ? this.sizeForm.dimensionFontIsItalic : DEFAULT_SIZE.dimensionFontIsItalic
this.sizeForm.dimensionLetterSpace = this.sizeForm.dimensionLetterSpace ? this.sizeForm.dimensionLetterSpace : DEFAULT_SIZE.dimensionLetterSpace
this.sizeForm.dimensionFontShadow = this.sizeForm.dimensionFontShadow ? this.sizeForm.dimensionFontShadow : DEFAULT_SIZE.dimensionFontShadow
this.sizeForm.hPosition = this.sizeForm.hPosition ? this.sizeForm.hPosition : DEFAULT_SIZE.hPosition
this.sizeForm.vPosition = this.sizeForm.vPosition ? this.sizeForm.vPosition : DEFAULT_SIZE.vPosition
}
}
},

View File

@ -984,6 +984,54 @@
@change="changeBarSizeCase('spaceSplit')"
/>
</el-form-item>
<el-form-item
v-show="showProperty('hPosition')"
:label="$t('chart.h_position')"
class="form-item"
>
<el-select
v-model="sizeForm.hPosition"
:placeholder="$t('chart.h_position')"
@change="changeBarSizeCase('hPosition')"
>
<el-option
value="start"
:label="$t('chart.p_left')"
>{{ $t('chart.p_left') }}</el-option>
<el-option
value="center"
:label="$t('chart.p_center')"
>{{ $t('chart.p_center') }}</el-option>
<el-option
value="end"
:label="$t('chart.p_right')"
>{{ $t('chart.p_right') }}</el-option>
</el-select>
</el-form-item>
<el-form-item
v-show="showProperty('vPosition')"
:label="$t('chart.v_position')"
class="form-item"
>
<el-select
v-model="sizeForm.vPosition"
:placeholder="$t('chart.v_position')"
@change="changeBarSizeCase('vPosition')"
>
<el-option
value="start"
:label="$t('chart.p_top')"
>{{ $t('chart.p_top') }}</el-option>
<el-option
value="center"
:label="$t('chart.p_center')"
>{{ $t('chart.p_center') }}</el-option>
<el-option
value="end"
:label="$t('chart.p_bottom')"
>{{ $t('chart.p_bottom') }}</el-option>
</el-select>
</el-form-item>
</div>
<!--text&label-end-->
<!--scatter-begin-->
@ -1384,6 +1432,9 @@ export default {
this.sizeForm.dimensionFontIsItalic = this.sizeForm.dimensionFontIsItalic ? this.sizeForm.dimensionFontIsItalic : DEFAULT_SIZE.dimensionFontIsItalic
this.sizeForm.dimensionLetterSpace = this.sizeForm.dimensionLetterSpace ? this.sizeForm.dimensionLetterSpace : DEFAULT_SIZE.dimensionLetterSpace
this.sizeForm.dimensionFontShadow = this.sizeForm.dimensionFontShadow ? this.sizeForm.dimensionFontShadow : DEFAULT_SIZE.dimensionFontShadow
this.sizeForm.hPosition = this.sizeForm.hPosition ? this.sizeForm.hPosition : DEFAULT_SIZE.hPosition
this.sizeForm.vPosition = this.sizeForm.vPosition ? this.sizeForm.vPosition : DEFAULT_SIZE.vPosition
}
}
},

View File

@ -16,7 +16,6 @@
:min="0"
:max="maxTop"
class="hide-icon-number"
@change="topOnChange"
>
<template slot="append">px</template>
</el-input>
@ -33,7 +32,6 @@
:min="0"
:max="maxLeft"
class="hide-icon-number"
@change="leftOnChange"
>
<template slot="append">px</template>
</el-input>
@ -50,7 +48,6 @@
:max="maxWidth"
type="number"
class="hide-icon-number"
@change="widthOnChange"
>
<template slot="append">px</template>
</el-input>
@ -59,7 +56,6 @@
:label="$t('panel.space_height')"
:min="0"
class="form-item"
prop="marginTop"
>
<el-input
v-model="styleInfo.height"
@ -67,7 +63,6 @@
:min="0"
:max="maxHeight"
class="hide-icon-number"
@change="heightOnChange"
>
<template slot="append">px</template>
</el-input>
@ -87,7 +82,7 @@ export default {
data() {
return {
maxHeight: 2000,
maxTop: 40000
maxTop: 20000
}
},
computed: {
@ -104,7 +99,20 @@ export default {
'componentGap'
])
},
watch: {},
watch: {
'styleInfo.top': function() {
this.topOnChange()
},
'styleInfo.left': function() {
this.leftOnChange()
},
'styleInfo.width': function() {
this.widthOnChange()
},
'styleInfo.height': function() {
this.heightOnChange()
}
},
mounted() {
},
methods: {

View File

@ -218,6 +218,7 @@ import { listApiDatasource, post, isKettleRunning } from '@/api/dataset/dataset'
import { dbPreview, engineMode } from '@/api/system/engine'
import cancelMix from './cancelMix'
import msgCfm from '@/components/msgCfm/index'
import { pySort } from './util'
export default {
name: 'AddApi',
@ -398,7 +399,7 @@ export default {
},
initDataSource() {
listApiDatasource().then((response) => {
this.options = response.data
this.options = pySort(response.data)
})
},
kettleState() {

View File

@ -225,6 +225,8 @@ import { listDatasource, post, isKettleRunning } from '@/api/dataset/dataset'
import { engineMode, dbPreview } from '@/api/system/engine'
import msgCfm from '@/components/msgCfm/index'
import cancelMix from './cancelMix'
import { pySort } from './util'
export default {
name: 'AddDB',
mixins: [msgCfm, cancelMix],
@ -415,7 +417,7 @@ export default {
},
initDataSource() {
listDatasource().then((response) => {
this.options = response.data.filter((item) => item.type !== 'api')
this.options = pySort(response.data.filter((item) => item.type !== 'api'))
})
},
kettleState() {

View File

@ -109,6 +109,7 @@
@click="
showTable = false
dataTable = ''
;keywords = ''
"
><i class="el-icon-arrow-left" /> {{ $t('chart.back') }}</span>
<span v-else>{{ $t('deDataset.data_reference') }}</span>
@ -147,13 +148,15 @@
>{{
$t('deDataset.to_start_using')
}}</span>
<div
v-else-if="dataSource && !dataTable"
<template v-else>
<el-input :placeholder="$t('fu.search_bar.please_input')" style="padding: 5px" size="small" v-model="keywords"></el-input>
<div
v-if="dataSource && !dataTable"
v-loading="tableLoading"
class="item-list"
>
<div
v-for="ele in tableData"
v-for="ele in tableDataCopy"
:key="ele.name"
class="table-or-field"
@click="typeSwitch(ele)"
@ -173,10 +176,11 @@
</div>
<div
v-else-if="dataSource && dataTable"
v-loading="tableLoading"
class="item-list"
>
<div
v-for="ele in fieldData"
v-for="ele in fieldDataCopy"
:key="ele.fieldName"
class="table-or-field field"
>
@ -193,6 +197,8 @@
/>
</div>
</div>
</template>
</div>
<div class="sql-table">
<div
@ -559,6 +565,7 @@ import 'codemirror/addon/hint/show-hint'
import { engineMode } from '@/api/system/engine'
import msgCfm from '@/components/msgCfm/index'
import cancelMix from './cancelMix'
import { pySort } from './util'
import _ from 'lodash'
import GridTable from '@/components/gridTable/index.vue'
export default {
@ -579,6 +586,7 @@ export default {
pageSize: 10,
total: 0
},
keywords: '',
sqlData: [],
dataSource: '',
loading: false,
@ -605,6 +613,8 @@ export default {
completeSingle: false //
}
},
tableDataCopy: [],
fieldDataCopy: [],
errImg: require('@/assets/error.png'),
initImg: require('@/assets/None.png'),
sqlHeight: 248,
@ -685,6 +695,21 @@ export default {
handler: function() {
this.calHeight()
}
},
keywords(val) {
if (!val) {
this.tableDataCopy = this.arrSort([...this.tableData], 'name')
this.fieldDataCopy = this.arrSort([...this.fieldData])
return
}
if (this.dataSource && !this.dataTable) {
this.tableDataCopy = this.arrSort(this.tableData.filter(ele => ele.name.includes(val)), 'name')
}
if (this.dataSource && this.dataTable) {
this.fieldDataCopy = this.arrSort(this.fieldData.filter(ele => ele.fieldName.includes(val)))
}
}
},
beforeDestroy() {
@ -729,16 +754,22 @@ export default {
this.listSqlLog()
},
getField(name) {
this.tableLoading = true
post('/dataset/table/getFields', {
dataSourceId: this.dataSource,
info: JSON.stringify({ table: name })
}).then((res) => {
this.fieldData = res.data
this.fieldDataCopy = this.arrSort([...this.fieldData])
})
.finally(() => {
this.tableLoading = false
})
},
typeSwitch({ name }) {
this.showTable = true
this.dataTable = name
this.keywords = ''
this.getField(name)
},
mousedownDrag() {
@ -768,6 +799,7 @@ export default {
})
},
changeDatasource() {
this.keywords = ''
for (let i = 0; i < this.options.length; i++) {
if (this.options[i].id === this.dataSource) {
this.selectedDatasource = this.options[i]
@ -787,11 +819,19 @@ export default {
post('/datasource/getTables/' + this.dataSource, {})
.then((response) => {
this.tableData = response.data
this.tableDataCopy = this.arrSort([...this.tableData], 'name')
})
.finally(() => {
this.tableLoading = false
})
},
arrSort(arr = [], field = 'fieldName') {
arr.sort((a, b) => {
return a[field][0].toLowerCase().charCodeAt() - b[field][0].toLowerCase().charCodeAt()
})
return arr
},
calHeight: _.debounce(function() {
const sqlHeight = Math.max(this.sqlHeight, 248)
const currentHeight = document.documentElement.clientHeight
@ -799,7 +839,7 @@ export default {
}, 200),
initDataSource() {
return listDatasource().then((response) => {
this.options = response.data.filter((item) => item.type !== 'api')
this.options = pySort(response.data.filter((item) => item.type !== 'api'))
})
},
@ -1119,7 +1159,7 @@ export default {
.item-list {
padding: 16px 8px;
height: calc(100vh - 200px);
height: calc(100vh - 242px);
overflow: auto;
.table-or-field {
height: 40px;

View File

@ -0,0 +1,12 @@
import pyjs from 'js-pinyin'
export function zh2py(str) {
return pyjs.getFullChars(str).toLowerCase().charCodeAt()
}
export function pySort(arr = []) {
arr.sort((a, b) => {
return zh2py(a.name[0]) - zh2py(b.name[0])
})
return arr
}

View File

@ -263,7 +263,7 @@ export default {
.info-item {
font-family: PingFang SC;
font-weight: 400;
margin: 6px 0;
margin: 6px 0 12px 0;
}
.info-title {
margin: 0!important;

View File

@ -128,7 +128,7 @@
/>
<ul
class="infinite-list autochecker-list"
style="overflow: auto"
style="overflow: auto;height: 231px"
>
<li
v-for="i in checkListWithFilter"
@ -218,7 +218,7 @@
</ul>
<div class="right-menu-foot">
<div class="footer-left">
{{ $t("auth.added") }} {{ checklist.length }}
&nbsp;
</div>
<div
class="confirm-btn"

View File

@ -923,7 +923,7 @@ export default {
}
}
const { queryType = 'dataset', id } = data
const { queryType = 'dataset', id, name } = data
if (checkPermission(['relationship:read'])) {
let hasSubRelation = false
await getDatasetRelationship(id).then((res) => {
@ -938,7 +938,7 @@ export default {
options.templateDel = msgContent
options.confirmButtonText = undefined
options.type = 'danger'
options.linkTo = this.linkTo.bind(this, { queryType, id })
options.linkTo = this.linkTo.bind(this, { queryType, id, name })
this.withLink(options, this.$t('commons.delete'))
return
}

View File

@ -77,7 +77,7 @@
:label="dialogTitleLabel"
prop="name"
>
<el-input v-model="templateEditForm.name" />
<el-input v-model="templateEditForm.name"/>
</el-form-item>
<el-form-item
:label="$t('app_template.app_group_icon')"
@ -95,7 +95,7 @@
:http-request="upload"
:file-list="fileList"
>
<i class="el-icon-plus" />
<i class="el-icon-plus"/>
</el-upload>
<el-dialog
top="25vh"
@ -147,6 +147,23 @@
@closeEditTemplateDialog="closeEditTemplateDialog"
/>
</el-dialog>
<!--导入templatedialog-->
<el-dialog
:title="$t('app_template.move_item') "
:visible.sync="moveItemDialogShow"
:show-close="true"
class="de-dialog-form"
width="300px"
>
<template-move-list
:template-list="templateList"
:source-template-info="currentMoveItem"
@closeDialog="moveItemDialogShow=false"
@templateMoveClose="templateMoveClose"
>
</template-move-list>
</el-dialog>
</div>
</template>
@ -159,10 +176,11 @@ import elementResizeDetectorMaker from 'element-resize-detector'
import msgCfm from '@/components/msgCfm/index'
import { uploadFileResult } from '@/api/staticResource/staticResource'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
import TemplateMoveList from '@/views/panel/appTemplate/component/TemplateMoveList'
export default {
name: 'AppTemplateContent',
components: { TemplateList, TemplateItem, TemplateImport },
components: { TemplateMoveList, TemplateList, TemplateItem, TemplateImport },
mixins: [msgCfm],
props: {
showPosition: {
@ -173,6 +191,8 @@ export default {
},
data() {
return {
moveItemDialogShow: false,
currentMoveItem: {},
templateOptType: 'add',
currentAppTemplateInfo: null,
fileList: [],
@ -302,6 +322,9 @@ export default {
case 'update':
this.updateAppTemplate(data)
break
case 'move':
this.moveTo(data)
break
default:
break
}
@ -312,6 +335,10 @@ export default {
this.currentAppTemplateInfo = data
this.templateDialog.pid = data.pid
},
moveTo(data) {
this.moveItemDialogShow = true
this.currentMoveItem = data
},
templateDeleteConfirm(template) {
const options = {
title: '是否卸载当前应用?',
@ -349,6 +376,10 @@ export default {
})
}
},
templateMoveClose() {
this.moveItemDialogShow = false
this.showCurrentTemplate(this.currentTemplateId, this.currentTemplateLabel)
},
showTemplateEditDialog(type, templateInfo) {
this.templateEditForm = null
this.formType = type

View File

@ -29,20 +29,26 @@
trigger="click"
@command="handleCommand"
>
<i class="el-icon-more" />
<i class="el-icon-more"/>
<el-dropdown-menu
slot="dropdown"
class="de-card-dropdown"
>
<slot>
<el-dropdown-item command="update">
<i class="el-icon-edit" />
<i class="el-icon-edit"/>
{{ $t('commons.update') }}
</el-dropdown-item>
<el-dropdown-item command="delete">
<i class="el-icon-delete" />
<i class="el-icon-delete"/>
{{ $t('commons.uninstall') }}
</el-dropdown-item>
<el-dropdown-item
icon="el-icon-right"
command="move"
>
{{ $t('app_template.move') }}
</el-dropdown-item>
</slot>
</el-dropdown-menu>
</el-dropdown>
@ -84,6 +90,7 @@
</template>
<script>
import { imgUrlTrans } from '@/components/canvas/utils/utils'
export default {
props: {
showPosition: {

View File

@ -250,8 +250,8 @@ export default {
}
li.select {
background: var(--deWhiteHover, #3370ff);
color: var(--TextActive, #f4f4f5);
background: var(--deWhiteHover, #ecf5ff) !important;
color: var(--TextActive, #3370ff) !important;
}
.de-btn-fix {

View File

@ -0,0 +1,229 @@
<template xmlns:el-col="http://www.w3.org/1999/html">
<div class="de-template-list">
<el-input
v-model="templateFilterText"
:placeholder="$t('system_parameter_setting.search_keywords')"
size="small"
class="de-input-search"
clearable
>
<svg-icon
slot="prefix"
icon-class="de-search"
/>
</el-input>
<el-empty
v-if="!templateListComputed.length && templateFilterText === ''"
:image="noneImg"
:description="$t('components.no_classification')"
/>
<el-empty
v-if="!templateListComputed.length && templateFilterText !== ''"
:image="nothingImg"
:description="$t('components.relevant_content_found')"
/>
<ul>
<li
v-for="ele in templateListComputed"
:key="ele.name"
:class="[{ select: activeTemplate === ele.id }]"
@click="nodeClick(ele)"
>
<img
:src="iconImgRul(ele.icon)"
style="margin-right: 8px;border-radius: 4px"
width="24"
height="24"
>
<span>{{ ele.name }}</span>
</li>
</ul>
<el-row class="de-root-class">
<deBtn
secondary
@click="cancel()"
>{{
$t('commons.cancel')
}}
</deBtn>
<deBtn
type="primary"
@click="save()"
:disabled="!activeTemplate"
>{{
$t('commons.confirm')
}}
</deBtn>
</el-row>
</div>
</template>
<script>
import msgCfm from '@/components/msgCfm/index'
import { imgUrlTrans } from '@/components/canvas/utils/utils'
import { move } from '@/api/system/appTemplate'
export default {
name: 'TemplateMoveList',
components: {},
mixins: [msgCfm],
props: {
sourceTemplateInfo: {
type: Object
},
templateList: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {
templateFilterText: '',
activeTemplate: '',
noneImg: require('@/assets/None.png'),
nothingImg: require('@/assets/nothing.png')
}
},
computed: {
templateListComputed() {
if (!this.templateFilterText) {
return this.templateList.filter((ele) =>
ele.id !== this.sourceTemplateInfo.pid
)
}
return this.templateList.filter((ele) =>
ele.name.includes(this.templateFilterText) && ele.id !== this.sourceTemplateInfo.pid
)
}
},
methods: {
iconImgRul(iconUrl) {
return imgUrlTrans(iconUrl)
},
cancel() {
this.$emit('closeDialog')
},
save() {
const request = {
id: this.sourceTemplateInfo.id,
pid: this.activeTemplate,
name: this.sourceTemplateInfo.name
}
move(request).then((response) => {
this.$emit('templateMoveClose')
})
},
showPositionCheck(requiredPosition) {
return this.showPosition === requiredPosition
},
nodeClick({ id, name }) {
this.activeTemplate = id
}
}
}
</script>
<style scoped lang="scss">
.de-template-list {
height: 380px;
overflow-y: hidden;
position: relative;
ul {
margin: 16px 0 20px 0;
padding: 0;
overflow-y: auto;
max-height: calc(100% - 90px);
}
li {
list-style: none;
width: 100%;
box-sizing: border-box;
height: 40px;
padding: 0 30px 0 12px;
display: flex;
align-items: center;
border-radius: 4px;
color: var(--deTextPrimary, #1f2329);
font-family: "PingFang SC";
font-style: normal;
font-weight: 500;
font-size: 14px;
cursor: pointer;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.folder {
color: #8f959e;
margin-right: 9px;
}
.more {
position: absolute;
top: 50%;
right: 10px;
transform: translateY(-50%);
display: none;
.el-icon-more {
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
font-size: 12px;
color: #646a73;
cursor: pointer;
}
.el-icon-more:hover {
background: rgba(31, 35, 41, 0.1);
border-radius: 4px;
}
.el-icon-more:active {
background: rgba(31, 35, 41, 0.2);
border-radius: 4px;
}
}
&:hover {
background: rgba(31, 35, 41, 0.1);
.more {
display: block;
}
}
}
li.select {
background: var(--deWhiteHover, #ecf5ff) !important;
color: var(--TextActive, #3370ff) !important;
}
.de-btn-fix {
position: absolute;
bottom: 0;
left: 0;
}
}
.de-template-dropdown {
margin-top: 0 !important;
.popper__arrow {
display: none !important;
}
}
.de-root-class {
bottom: 0;
width: 100%;
position: absolute;
text-align: right;
}
</style>

View File

@ -165,12 +165,12 @@
v-show=" show &&showIndex===1"
:canvas-id="canvasId"
/>
<subject-setting v-show=" show &&showIndex===2" />
<assist-component v-show=" show &&showIndex===3" />
<subject-setting v-show=" show &&showIndex===2"/>
<assist-component v-show=" show &&showIndex===3"/>
</div>
</el-drawer>
<!--PC端画布区域-->
<canvas-opt-bar v-if="!previewVisible&&!mobileLayoutStatus" />
<canvas-opt-bar v-if="!previewVisible&&!mobileLayoutStatus"/>
<de-canvas
v-if="!previewVisible&&!mobileLayoutStatus"
ref="canvasMainRef"
@ -196,7 +196,7 @@
:style="customCanvasMobileStyle"
class="this_mobile_canvas"
>
<el-row class="this_mobile_canvas_top" />
<el-row class="this_mobile_canvas_top"/>
<el-row class="this_mobile_canvas_inner_top">
{{ panelInfo.name }}
</el-row>
@ -205,7 +205,7 @@
class="this_mobile_canvas_main"
:style="mobileCanvasStyle"
>
<canvas-opt-bar v-if="!previewVisible&&mobileLayoutStatus" />
<canvas-opt-bar v-if="!previewVisible&&mobileLayoutStatus"/>
<de-canvas
v-if="!previewVisible&&mobileLayoutStatus"
ref="canvasMainRef"
@ -243,14 +243,14 @@
/>
</el-col>
</el-row>
<el-row class="this_mobile_canvas_bottom" />
<el-row class="this_mobile_canvas_bottom"/>
</div>
</el-col>
<el-col
:span="16"
class="this_mobile_canvas_cell this_mobile_canvas_wait_cell"
>
<component-wait />
<component-wait/>
</el-col>
</el-row>
</de-main-container>
@ -268,7 +268,7 @@
/>
</div>
<div v-if="showBatchViewToolsAside">
<chart-style-batch-set />
<chart-style-batch-set/>
</div>
<div v-if="!showViewToolsAside&&!showBatchViewToolsAside">
<el-row style="height: 40px">
@ -287,7 +287,7 @@
>{{ $t('panel.position_adjust') }}</span>
</el-row>
<el-row>
<position-adjust v-if="curComponent&&!curComponent.auxiliaryMatrix" />
<position-adjust v-if="curComponent&&!curComponent.auxiliaryMatrix"/>
<div
v-else
class="view-selected-message-class"
@ -792,6 +792,9 @@ export default {
},
previewVisible(val) {
this.$store.commit('setPreviewVisible', val)
if (!val) {
listenGlobalKeyDown()
}
},
panelInfo: {
handler(newVal, oldVla) {

View File

@ -61,7 +61,6 @@
<span
slot-scope="{ node, data }"
style="display: flex;flex: 1;width: 0%;"
class="custom-tree-node"
>
<span>
<svg-icon
@ -275,7 +274,7 @@
:control-attrs="myAttrs"
:child-views="childViews"
:dataset-params="datasetParams"
:activeName="activeName"
:active-name="activeName"
/>
<filter-foot :element="currentElement" />

View File

@ -117,7 +117,7 @@
@change="checkedViewsChange"
>
<el-checkbox
v-for="(item ) in childViews.viewInfos"
v-for="(item ) in curTableViews"
:key="item.id"
:label="item.id"
class="de-checkbox"
@ -308,6 +308,12 @@ export default {
computed: {
fieldIds() {
return this.element.options.attrs.fieldId || []
},
curTableViews() {
const tableIdList = this.element.options.attrs.dragItems.map(item => item.tableId) || []
const views = this.childViews.viewInfos.filter(view => tableIdList.includes(view.tableId))
return views
}
},
watch: {

View File

@ -69,6 +69,10 @@ export const CANVAS_STYLE = {
showGrid: false,
matrixBase: 4 // 当前matrix的基数 是pcMatrixCount的几倍
}, // 辅助设计
pdfPageLine: {
showPageLine: false,
proportion: null
},
refreshViewEnable: true, // 开启视图刷新(默认开启)
refreshViewLoading: true, // 仪表板视图loading提示
refreshUnit: 'minute', // 仪表板刷新时间带外 默认 分钟
@ -82,6 +86,11 @@ export const AIDED_DESIGN = {
matrixBase: 1 // 当前matrix的基数 是pcMatrixCount的几倍
}
export const PAGE_LINE_DESIGN = {
showPageLine: false,
proportion: null
}
export const DEFAULT_COMMON_CANVAS_STYLE_STRING = {
...CANVAS_STYLE
}

View File

@ -253,8 +253,8 @@ export default {
}
li.select {
background: var(--deWhiteHover, #3370ff);
color: var(--TextActive, #f4f4f5);
background: var(--deWhiteHover, #e0eaff) !important;
color: var(--TextActive, #3370ff) !important;
}
.de-btn-fix {

View File

@ -1,6 +1,9 @@
<template>
<div style="width: 100%;display: flex;justify-content: center;">
<el-card class="box-card about-card">
<el-card
class="box-card about-card"
:class="dynamicCardClass"
>
<div
slot="header"
class="clearfix license-header"
@ -48,6 +51,18 @@
<span>{{ build }}</span>
</td>
</tr>
<tr v-if="license.serialNo">
<th>{{ $t('about.serial_no') }}</th>
<td>
<span>{{ license.serialNo }}</span>
</td>
</tr>
<tr v-if="license.remark">
<th>{{ $t('about.remark') }}</th>
<td>
<span>{{ license.remark }}</span>
</td>
</tr>
</table>
</div>
@ -98,6 +113,15 @@ export default {
}
},
computed: {
dynamicCardClass() {
if (this.license?.serialNo && this.license?.remark) {
return 'about-card-max'
}
if (!this.license?.serialNo && !this.license?.remark) {
return ''
}
return 'about-card-medium'
},
...mapGetters([
'user'
])
@ -137,7 +161,9 @@ export default {
expired: result.license ? result.license.expired : '',
count: result.license ? result.license.count : '',
version: result.license ? result.license.version : '',
edition: result.license ? result.license.edition : ''
edition: result.license ? result.license.edition : '',
serialNo: result.license ? result.license.serialNo : '',
remark: result.license ? result.license.remark : ''
}
},
importLic(file) {
@ -188,6 +214,12 @@ export default {
padding: 0;
}
}
.about-card-medium {
height: 415px !important;
}
.about-card-max {
height: 430px !important;
}
.license-header {
height: 100px;
background-image: url('../../../assets/license_header.png');

View File

@ -535,6 +535,64 @@
/>
</el-form-item>
</div>
<el-form-item
:label="$t('datasource.isUseJsonPath')"
>
<el-input
:disabled="!apiItem.useJsonPath"
v-model="apiItem.jsonPath"
:placeholder="$t('datasource.jsonpath_info')"
class="input-with-select"
size="small"
>
<el-select
slot="prepend"
v-model="apiItem.useJsonPath"
style="width: 100px"
size="small"
>
<el-option
v-for="item in isUseJsonPath"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
<el-button
:disabled="!apiItem.useJsonPath"
slot="append"
@click="showApiData"
>{{ $t('datasource.show_api_data') }}
</el-button>
</el-input>
</el-form-item>
<div class="row-rules" v-show="apiItem.useJsonPath">
<span>{{ $t('datasource.column_info') }}</span>
</div>
<div class="table-container de-svg-in-table" v-show="apiItem.useJsonPath">
<el-table
ref="apiItemTable"
:data="originFieldItem.jsonFields"
style="width: 100%"
row-key="jsonPath"
>
<el-table-column
class-name="checkbox-table"
prop="originName"
:label="$t('dataset.parse_filed')"
:show-overflow-tooltip="true"
width="255"
>
<template slot-scope="scope">
{{ scope.row.originName }}
</template>
</el-table-column>
</el-table>
</div>
</el-form>
</el-row>
<el-row v-show="active === 2">
@ -567,8 +625,8 @@
<el-checkbox
:key="scope.row.jsonPath"
v-model="scope.row.checked"
:disabled="scope.row.disabled"
@change="handleCheckAllChange(scope.row)"
:disabled="scope.row.disabled || apiItem.useJsonPath"
@change="handleCheckAllChange(apiItem, scope.row, 'plxTable')"
>
{{ scope.row.originName }}
</el-checkbox>
@ -973,12 +1031,18 @@ export default {
originName: 'comments',
deExtractType: 0
}
]
],
useJsonPath: false,
jsonPath: ''
},
reqOptions: [
{ id: 'GET', label: 'GET' },
{ id: 'POST', label: 'POST' }
],
isUseJsonPath: [
{ id: true, label: this.$t('commons.yes') },
{ id: false, label: this.$t('commons.no') }
],
loading: false,
responseData: { type: 'HTTP', responseResult: {}, subRequestResults: [] },
api_step2_active_name: 'first',
@ -1015,7 +1079,11 @@ export default {
value: 3
}
],
certinKey: false
certinKey: false,
originFieldItem: {
jsonFields: [],
fields: []
},
}
},
methods: {
@ -1071,6 +1139,10 @@ export default {
this.$message.error(i18n.t('datasource.has_repeat_name'))
return
}
if (this.apiItem.useJsonPath && !this.apiItem.jsonPath) {
this.$message.error(i18n.t('datasource.please_input_dataPath'))
return
}
this.$refs.apiItemBasicInfo.validate((valid) => {
if (valid) {
const data = Base64.encode(JSON.stringify(this.apiItem))
@ -1085,8 +1157,10 @@ export default {
this.active++
this.apiItem.jsonFields = res.data.jsonFields
this.apiItem.fields = []
this.handleFiledChange()
this.previewData()
this.handleFiledChange(this.apiItem)
this.$nextTick(() => {
this.$refs.plxTable?.reloadData(this.previewData(this.apiItem))
})
})
.catch((res) => {
this.loading = false
@ -1099,6 +1173,32 @@ export default {
})
}
},
showApiData(){
if (this.apiItem.useJsonPath && !this.apiItem.jsonPath) {
this.$message.error(i18n.t('datasource.please_input_dataPath'))
return
}
this.$refs.apiItemBasicInfo.validate((valid) => {
if (valid) {
const data = Base64.encode(JSON.stringify(this.apiItem))
this.loading = true
checkApiDatasource({'data': data, 'type': 'apiStructure'})
.then((res) => {
res.data.jsonFields.forEach(((item) => {
item.checked = false
}))
this.originFieldItem.jsonFields = res.data.jsonFields
this.loading = false
this.$success(i18n.t('commons.success'))
})
.catch((res) => {
this.loading = false
})
} else {
return false
}
})
},
before() {
this.active--
},
@ -1200,12 +1300,21 @@ export default {
cancelItem({ name }) {
this.$refs[`apiTable${name}`][0].doClose()
},
handleCheckAllChange(row) {
handleCheckAllChange(apiItem, row, ref) {
this.errMsg = []
this.handleCheckChange(row)
this.apiItem.fields = []
this.handleFiledChange(row)
this.previewData()
this.handleCheckChange(apiItem, row)
apiItem.fields = []
this.handleFiledChange(apiItem, row)
if(ref === 'plxTable'){
this.$nextTick(() => {
this.$refs.plxTable?.reloadData(this.previewData(this.apiItem))
})
}else {
this.$nextTick(() => {
this.$refs.originPlxTable?.reloadData(this.previewData(this.originFieldItem))
})
}
if (this.errMsg.length) {
this.$message.error(
[...new Set(this.errMsg)].join(',') +
@ -1214,24 +1323,24 @@ export default {
)
}
},
handleFiledChange() {
for (var i = 0; i < this.apiItem.jsonFields.length; i++) {
handleFiledChange(apiItem) {
for (var i = 0; i < apiItem.jsonFields.length; i++) {
if (
this.apiItem.jsonFields[i].checked &&
this.apiItem.jsonFields[i].children === undefined
apiItem.jsonFields[i].checked &&
apiItem.jsonFields[i].children === undefined
) {
this.apiItem.fields.push(this.apiItem.jsonFields[i])
apiItem.fields.push(apiItem.jsonFields[i])
}
if (this.apiItem.jsonFields[i].children !== undefined) {
this.handleFiledChange2(this.apiItem.jsonFields[i].children)
if (apiItem.jsonFields[i].children !== undefined) {
this.handleFiledChange2(apiItem, apiItem.jsonFields[i].children)
}
}
},
handleFiledChange2(jsonFields) {
handleFiledChange2(apiItem, jsonFields) {
for (var i = 0; i < jsonFields.length; i++) {
if (jsonFields[i].checked && jsonFields[i].children === undefined) {
for (var j = 0; j < this.apiItem.fields.length; j++) {
if (this.apiItem.fields[j].name === jsonFields[i].name) {
for (var j = 0; j < apiItem.fields.length; j++) {
if (apiItem.fields[j].name === jsonFields[i].name) {
jsonFields[i].checked = false
this.$nextTick(() => {
jsonFields[i].checked = false
@ -1239,52 +1348,52 @@ export default {
this.errMsg.push(jsonFields[i].name)
}
}
this.apiItem.fields.push(jsonFields[i])
apiItem.fields.push(jsonFields[i])
}
if (jsonFields[i].children !== undefined) {
this.handleFiledChange2(jsonFields[i].children)
}
}
},
previewData() {
previewData(apiItem) {
this.showEmpty = false
const data = []
let maxPreviewNum = 0
for (let j = 0; j < this.apiItem.fields.length; j++) {
for (let j = 0; j < apiItem.fields.length; j++) {
if (
this.apiItem.fields[j].value &&
this.apiItem.fields[j].value.length > maxPreviewNum
apiItem.fields[j].value &&
apiItem.fields[j].value.length > maxPreviewNum
) {
maxPreviewNum = this.apiItem.fields[j].value.length
maxPreviewNum = apiItem.fields[j].value.length
}
}
for (let i = 0; i < maxPreviewNum; i++) {
data.push({})
}
for (let i = 0; i < this.apiItem.fields.length; i++) {
for (let j = 0; j < this.apiItem.fields[i].value.length; j++) {
for (let i = 0; i < apiItem.fields.length; i++) {
for (let j = 0; j < apiItem.fields[i].value.length; j++) {
this.$set(
data[j],
this.apiItem.fields[i].name,
this.apiItem.fields[i].value[j]
apiItem.fields[i].name,
apiItem.fields[i].value[j]
)
}
this.$nextTick(() => {
this.$refs.plxTable?.reloadData(data)
})
}
this.showEmpty = this.apiItem.fields.length === 0
this.showEmpty = apiItem.fields.length === 0
return data
},
handleCheckChange(node) {
handleCheckChange(apiItem, node) {
if (node.children !== undefined) {
node.children.forEach((item) => {
item.checked = node.checked
this.handleCheckChange(item)
this.handleCheckChange(apiItem, item)
})
}
},
fieldNameChange(row) {
this.previewData()
this.$nextTick(() => {
this.$refs.plxTable?.reloadData(this.previewData(this.apiItem))
})
},
fieldTypeChange(row) {}
}

View File

@ -118,7 +118,33 @@
:key="item.id"
:label="item.name"
:value="item.id"
/>
>
<span
v-if="
item.status !== 'Error' &&
item.status !== 'Warning'
"
>
<svg-icon
icon-class="db-de"
/>
</span>
<span v-if="item.status === 'Error'">
<svg-icon
icon-class="de-ds-error"
class="ds-icon-scene"
/>
</span>
<span v-if="item.status === 'Warning'">
<svg-icon
icon-class="de-ds-warning"
class="ds-icon-scene"
/>
</span>
<span>
{{ item.name }}
</span>
</el-option>
</el-select>
</el-form-item>
</el-form>
@ -662,7 +688,7 @@ export default {
this.$emit('setParams', { ...this.params })
this.$nextTick(() => {
this.disabled = appMarketCheck ? !this.appMarketEdit : (Boolean(id) && showModel === 'show' && !this.canEdit)
if (this.configFromTabs.editor === 'editor') {
if (this.configFromTabs?.editor === 'editor') {
this.$emit('editeTodisable', true)
}
})
@ -992,6 +1018,7 @@ export default {
delete item.status
})
form.configuration = Base64.encode(JSON.stringify(form.apiConfiguration))
form.apiConfiguration = []
} else {
form.configuration = Base64.encode(JSON.stringify(form.configuration))
}
@ -1113,6 +1140,7 @@ export default {
}
})
}
this.$refs.dsForm.validate()
if (!status) {
return
}
@ -1129,6 +1157,7 @@ export default {
const data = JSON.parse(JSON.stringify(this.form))
if (data.type === 'api') {
data.configuration = Base64.encode(JSON.stringify(data.apiConfiguration))
data.apiConfiguration = []
} else {
data.configuration = Base64.encode(JSON.stringify(data.configuration))
}

View File

@ -760,7 +760,7 @@ export default {
params.link = this.$t('datasource.click_to_check')
params.content = this.$t('datasource.cannot_be_deleted_datasource')
params.templateDel = msgContent
params.linkTo = this.linkTo.bind(this, { queryType, id })
params.linkTo = this.linkTo.bind(this, { queryType, id, name: label })
this.withLink(params)
return
}

View File

@ -32,17 +32,17 @@ export default {
},
watch: {
chartSize: {
handler(val) {
if (this.myChart) {
this.myChart.resize(val)
}
},
deep: true
handler(val) {
if (this.myChart) {
this.myChart.resize(val)
}
},
deep: true
}
},
methods: {
getChartData(current) {
this.current = {...current}
this.current = { ...current }
const { queryType, num: id } = current
this.activeId = id
switch (queryType) {
@ -52,9 +52,14 @@ export default {
case 'dataset':
this.getDatasetRelationship(id)
break
case 'panel':
this.getPanelRelationship(id)
case 'panel': {
let targetId = id
if (current.nodeData?.source) {
targetId = current.nodeData.source
}
this.getPanelRelationship(targetId)
break
}
default:
break
}
@ -485,4 +490,4 @@ export default {
}
}
}
</script>
</script>

View File

@ -1,11 +1,14 @@
<template>
<div class="consanguinity">
<div
class="consanguinity"
@click.stop="resetFilter"
>
<div class="route-title">{{ $t('commons.consanguinity') }}</div>
<div class="container-wrapper">
<el-form
ref="form"
:rules="rules"
:inline="true"
ref="form"
:model="formInline"
class="de-form-inline"
>
@ -15,59 +18,115 @@
>
<el-select
v-model="formInline.queryType"
@change="queryTypeChange"
:placeholder="$t('fu.search_bar.please_select')"
@change="queryTypeChange"
@focus="resetFilter"
>
<el-option
v-for="item in queryTypeNameList"
:key="item.value"
:label="$t(item.label)"
:value="item.value"
>
</el-option>
/>
</el-select>
</el-form-item>
<el-form-item prop="dataSourceName" :label="queryTypeTitle">
<el-select
v-model="formInline.dataSourceName"
filterable
:placeholder="$t('fu.search_bar.please_select')"
<el-form-item
prop="dataSourceName"
:label="queryTypeTitle"
>
<el-popover
v-model="showTree"
placement="bottom"
trigger="manual"
:width="popoverSize"
popper-class="relation-popover"
>
<el-option
v-for="item in dataSourceNameList"
:key="item.value"
:label="item.label"
:value="item.value"
<el-tree
v-show="showTree"
ref="resourceTree"
accordion
node-key="id"
:indent="8"
:data="resourceTreeData"
:highlight-current="true"
:filter-node-method="filterNodeMethod"
:current-node-key="formInline.dataSourceName"
@node-click="nodeClick"
>
</el-option>
</el-select>
<span
slot-scope="{ data }"
>
<span>
<span>
<svg-icon
:icon-class="getIconClass(formInline.queryType, data)"
:class="getNodeClass(formInline.queryType, data)"
/>
</span>
<span
:title="data.name"
style="padding-right: 8px"
>
{{ data.name }}
</span>
</span>
</span>
</el-tree>
<el-select
ref="treeSelect"
slot="reference"
v-model="formInline.dataSourceName"
filterable
remote
:filter-method="filterMethod"
:title="nodeData.name"
popper-class="tree-select"
@focus="showTree = true"
>
<el-option
v-for="item in ignoredOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-popover>
</el-form-item>
<el-form-item style="float: right">
<de-btn type="primary" @click="onSubmit">{{
$t('commons.adv_search.search')
}}</de-btn>
<de-btn
type="primary"
@click="onSubmit"
>
{{ $t('commons.adv_search.search') }}
</de-btn>
</el-form-item>
</el-form>
<div class="select-icon">
<i
@click="activeQueryType('date')"
:class="[activeIcon === 'date' ? 'active-icon' : '']"
class="el-icon-date"
></i>
@click="activeQueryType('date')"
/>
<svg-icon
icon-class="sys-relationship"
:class="[activeIcon === 'share' ? 'active-icon' : '']"
@click="activeQueryType('share')"
/>
</div>
<div v-show="activeIcon === 'share'" id="consanguinity">
<div
v-show="activeIcon === 'share'"
id="consanguinity"
>
<consanguinity
:chartSize="chartSize"
:current="current"
ref="consanguinity"
:chart-size="chartSize"
:current="current"
/>
</div>
<div v-show="activeIcon === 'date'" class="consanguinity-table">
<div
v-show="activeIcon === 'date'"
class="consanguinity-table"
>
<grid-table
v-loading="loading"
:table-data="tableData"
@ -75,7 +134,11 @@
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<el-table-column :label="$t('table.id')" type="index" width="50" />
<el-table-column
:label="$t('table.id')"
type="index"
width="50"
/>
<el-table-column
prop="datasource"
:formatter="formatter"
@ -106,15 +169,14 @@ import {
getDatasetRelationship,
getPanelRelationship
} from '@/api/chart/chart.js'
import {
listDatasource,
getDatasetList,
getPanelGroupList
} from '@/api/dataset/dataset'
import { listDatasource } from '@/api/dataset/dataset'
import _ from 'lodash'
import GridTable from '@/components/gridTable/index.vue'
import consanguinity from './consanguinity.vue'
import { log } from '@antv/g2plot/lib/utils'
import { defaultTree, groupTree } from '@/api/panel/panel'
import { queryAuthModel } from '@/api/authModel/authModel'
import { data } from 'vue2-ace-editor'
export default {
name: 'Consanguinity',
components: { GridTable, consanguinity },
@ -128,7 +190,6 @@ export default {
queryType: [{ required: true, trigger: 'blur' }],
dataSourceName: [{ required: true, trigger: 'blur', message: this.$t('chart.name_can_not_empty') }]
},
dataSourceNameList: [],
queryTypeNameList: [
{
label: 'commons.datasource',
@ -155,19 +216,22 @@ export default {
currentPage: 1,
pageSize: 10,
total: 0
}
},
resourceTreeData: [],
ignoredOptions: [],
showTree: false,
nodeData: {},
popoverSize: 400,
currentNode: {}
}
},
computed: {
current() {
const { queryType = '', dataSourceName } = this.formInline
const obj =
this.dataSourceNameList.find((ele) => dataSourceName === ele.value) ||
{}
return {
queryType,
num: obj.value,
label: obj.label
queryType: this.formInline.queryType,
num: this.formInline.dataSourceName,
label: this.nodeData.name,
nodeData: this.nodeData
}
},
queryTypeTitle() {
@ -189,9 +253,9 @@ export default {
},
created() {
this.routerWithParams = this.$route.query
const { id, queryType } = this.routerWithParams
const { id, queryType, name } = this.routerWithParams
if (id && queryType) {
this.searchDetail(id, queryType)
this.searchDetail(id, queryType, name)
return
}
this.listDatasource()
@ -204,11 +268,12 @@ export default {
this.getChartSize()
},
methods: {
data,
activeQueryType(activeIcon) {
this.activeIcon = activeIcon
this.onSubmit()
},
async searchDetail(id, queryType) {
async searchDetail(id, queryType, name) {
switch (queryType) {
case 'datasource':
await this.listDatasource()
@ -223,6 +288,13 @@ export default {
break
}
this.formInline = { queryType, dataSourceName: id }
this.nodeData = { id, name }
this.ignoredOptions = [this.nodeData]
this.$refs.resourceTree.setCurrentKey(id)
const currentParents = this.$refs.resourceTree.getNodePath(this.nodeData)
currentParents.forEach((node) => {
this.$refs.resourceTree.store.nodesMap[node.id].expanded = true
})
this.getChartData()
},
getChartData() {
@ -234,9 +306,14 @@ export default {
case 'dataset':
this.getDatasetRelationship(id)
break
case 'panel':
this.getPanelRelationship(id)
case 'panel': {
let targetId = id
if (this.nodeData.source) {
targetId = this.nodeData.source
}
this.getPanelRelationship(targetId)
break
}
default:
break
}
@ -270,7 +347,7 @@ export default {
})
},
formatter(row, column, cellValue) {
return cellValue ? cellValue : '-'
return cellValue || '-'
},
initTable() {
this.paginationConfig.total = this.treeData.length
@ -302,7 +379,7 @@ export default {
}
})
},
getChartSize: _.debounce(function () {
getChartSize: _.debounce(function() {
const dom = document.querySelector(
this.activeIcon === 'date' ? '.consanguinity-table' : '#consanguinity'
)
@ -313,44 +390,67 @@ export default {
}, 200),
listDatasource() {
return listDatasource().then((res) => {
const arr = res?.data || []
this.dataSourceNameList = arr.map((ele) => ({
value: ele.id,
label: ele.name
}))
const dsArr = res?.data || []
const typeMap = {}
dsArr.forEach((item) => {
if (!typeMap[item.type]) {
typeMap[item.type] = [{ id: item.id, name: item.name, type: 'datasource' }]
this.resourceTreeData.push({
id: item.type,
name: item.typeDesc,
type: 'folder',
children: typeMap[item.type]
})
} else {
typeMap[item.type].push({ id: item.id, name: item.name, type: 'datasource' })
}
})
})
},
getDatasetList() {
return getDatasetList().then((res) => {
const arr = res?.data || []
this.dataSourceNameList = arr.map((ele) => ({
value: ele.id,
label: ele.name
}))
return queryAuthModel({ modelType: 'dataset' }, false).then((res) => {
this.resourceTreeData = res.data
})
},
getPanelGroupList() {
return getPanelGroupList().then((res) => {
const arr = res?.data || []
this.dataSourceNameList = arr.map((ele) => ({
value: ele.id,
label: ele.name
}))
return defaultTree({ panelType: 'system' }, true).then((res) => {
if (res.data?.length > 0) {
const defaultPanelTree = {
id: 'defaultPanel',
name: this.$t('panel.default_panel'),
nodeType: 'folder',
children: res.data
}
this.resourceTreeData.push(defaultPanelTree)
}
}).then(() => {
const form = {
panelType: 'self',
sort: 'create_time desc,node_type desc,name asc'
}
groupTree(form, true).then((res) => {
this.resourceTreeData = [...this.resourceTreeData, ...res.data]
})
})
},
queryTypeChange(val) {
this.formInline.dataSourceName = ''
this.dataSourceNameList = []
this.resourceTreeData = []
this.nodeData = {}
this.currentNode = {}
switch (val) {
case 'datasource':
case 'datasource': {
this.listDatasource()
break
case 'dataset':
}
case 'dataset': {
this.getDatasetList()
break
case 'panel':
}
case 'panel': {
this.getPanelGroupList()
break
}
default:
break
}
@ -374,6 +474,88 @@ export default {
handleCurrentChange(currentPage) {
this.paginationConfig.currentPage = currentPage
this.onSubmit()
},
getIconClass(queryType, nodeData) {
switch (queryType) {
case 'datasource': {
if (nodeData.type === 'folder') {
return 'scene'
}
return 'db-de'
}
case 'dataset': {
if (nodeData.modelInnerType === 'group') {
return 'scene'
}
return `ds-${nodeData.modelInnerType}`
}
case 'panel':
if (nodeData.nodeType === 'panel') {
let iconClass = 'panel-'
if (nodeData.mobileLayout) {
iconClass += 'mobile-'
}
iconClass += nodeData.status
return iconClass
}
return 'scene'
default:
break
}
},
getNodeClass(queryType, nodeData) {
switch (queryType) {
case 'dataset': {
if (nodeData.modelInnerType !== 'group') {
return `ds-icon-${nodeData.modelInnerType}`
}
return ''
}
case 'panel': {
if (nodeData.nodeType === 'panel') {
return 'ds-icon-scene'
}
return ''
}
default: {
return ''
}
}
},
filterNodeMethod(value, data) {
if (!value) {
return true
}
return data.name.toLowerCase().indexOf(value.toLowerCase()) !== -1
},
filterMethod(filterText) {
this.$refs.resourceTree.filter(filterText)
},
nodeClick(data, node) {
if (node.isLeaf) {
this.ignoredOptions = [{ id: data.id, name: data.name }]
this.formInline.dataSourceName = data.id
this.showTree = false
this.nodeData = data
this.currentNode = node
}
},
resetFilter() {
if (this.showTree) {
this.showTree = false
this.$refs.resourceTree.filter()
this.$refs.resourceTree.setCurrentKey(this.formInline.dataSourceName)
if (this.formInline.dataSourceName === '') {
this.$refs.resourceTree.setCurrentKey(null)
}
if (this.formInline.dataSourceName) {
const currentParents = this.$refs.resourceTree.getNodePath(this.nodeData).map((item) => item.id)
const nodesMap = this.$refs.resourceTree.store.nodesMap || {}
for (const key in nodesMap) {
nodesMap[key].expanded = currentParents.includes(key)
}
}
}
}
}
}
@ -428,4 +610,35 @@ export default {
}
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.custom-tree-node-list {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding: 0 8px;
}
.father .child {
/*display: none;*/
visibility: hidden;
}
.father:hover .child {
/*display: inline;*/
visibility: visible;
}
.relation-popover {
max-height: 70%;
overflow-y: scroll;
}
</style>

View File

@ -17,20 +17,3 @@ export default {
}
}
</script>
<style lang="scss" scoped>
.operator-bar {
width: 100%;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
.title {
font-family: PingFang SC;
font-size: 16px;
font-weight: 500;
line-height: 24px;
color: #1f2329;
}
}
</style>

View File

@ -223,7 +223,6 @@
</template>
<script>
import { PHONE_REGEX } from '@/utils/validate'
import { getDeptTree, treeByDeptId } from '@/api/system/dept'
import { addUser, editUser, allRoles, queryAssist } from '@/api/system/user'
import { pluginLoaded, defaultPwd, wecomStatus, dingtalkStatus, larkStatus } from '@/api/user'
@ -280,7 +279,7 @@ export default {
],
phone: [
{
pattern: PHONE_REGEX,
validator: this.phoneRegex,
message: this.$t('user.phone_format'),
trigger: 'blur'
}
@ -413,6 +412,16 @@ export default {
callback()
}
},
phoneRegex(rule, value, callback) {
const regep = new RegExp(/^1[3-9]\d{9}$/)
if (!regep.test(value)) {
const msg = this.$t('user.phone_format')
callback(new Error(msg))
} else {
callback()
}
},
validateUsername(rule, value, callback) {
const pattern = '^[a-zA-Z][a-zA-Z0-9\._-]*$'
const regep = new RegExp(pattern)

View File

@ -285,6 +285,7 @@
<el-button
slot="reference"
v-permission="['user:editPwd']"
:disabled="resetPwdDisabled(scope.row)"
class="de-text-btn mar16"
type="text"
>{{ $t("member.edit_password") }}</el-button>
@ -303,6 +304,7 @@
type="text"
@click="unlock(scope.row)"
>{{ $t("commons.unlock") }}</el-button>
<span v-else>&nbsp;</span>
</template>
</el-table-column>
</grid-table>
@ -436,6 +438,9 @@ export default {
bus.$off('reload-user-grid', this.search)
},
methods: {
resetPwdDisabled(row) {
return ((row.from ?? '') !== '') && row.from > 0
},
resizeObserver() {
this.resizeForFilter = new ResizeObserver(entries => {
if (!this.filterTexts.length) return

View File

@ -30,12 +30,12 @@
/>
</el-row>
<el-row class="top_banner_card">
<wizard-card :details="cardList[0]" />
<wizard-card :details="cardList[0]"/>
<wizard-card
:details="cardList[1]"
style="margin:0 24px 0 24px"
/>
<wizard-card-enterprise :details="cardList[2]" />
<wizard-card-enterprise :details="cardList[2]"/>
</el-row>
<el-row class="content_middle">
<div class="content_middle_left">
@ -44,15 +44,15 @@
<div class="content_middle_more"><a
target="_blank"
href="https://space.bilibili.com/510493147/channel/collectiondetail?sid=262774"
>{{ $t('wizard.more') }}<i class="el-icon-arrow-right" /></a></div>
>{{ $t('wizard.more') }}<i class="el-icon-arrow-right"/></a></div>
</el-row>
<el-row style="margin-top: 12px">
<video-card :details="videoList[0]" />
<video-card :details="videoList[0]"/>
<video-card
style="margin:0 12px 0 12px"
:details="videoList[1]"
/>
<video-card :details="videoList[2]" />
<video-card :details="videoList[2]"/>
</el-row>
</div>
<div class="content_middle_right">
@ -61,7 +61,7 @@
<div class="content_middle_more"><a
target="_blank"
href="https://blog.fit2cloud.com/?cat=321"
>{{ $t('wizard.more') }}<i class="el-icon-arrow-right" /></a></div>
>{{ $t('wizard.more') }}<i class="el-icon-arrow-right"/></a></div>
</el-row>
<el-row>
<ul class="ul-custom">
@ -93,10 +93,10 @@
</el-row>
<el-row class="contact_content">
{{ $t('wizard.web') }}<a
style="text-decoration:underline;"
target="_blank"
href="https://www.dataease.io"
>www.dataease.io</a>
style="text-decoration:underline;"
target="_blank"
href="https://www.dataease.io"
>www.dataease.io</a>
</el-row>
</div>
@ -154,7 +154,7 @@ export default {
content: this.$t('wizard.demo_video_hint'),
img: 'wizard_quick_start',
bgColor: '#E7F2FF',
href: 'https://www.bilibili.com/video/BV1i34y1v7hq/'
href: 'https://www.bilibili.com/video/BV1qG4y1F7uc/'
},
{
head: this.$t('wizard.online_document'),

View File

@ -6,7 +6,7 @@
<parent>
<artifactId>dataease-server</artifactId>
<groupId>io.dataease</groupId>
<version>1.18.1</version>
<version>1.18.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.dataease</groupId>
<artifactId>dataease-server</artifactId>
<version>1.18.1</version>
<version>1.18.2</version>
<packaging>pom</packaging>
<parent>