Merge branch 'dev' into pr@dev@fixSql

This commit is contained in:
taojinlong 2024-01-25 18:44:10 +08:00
commit 67bca48f77
54 changed files with 725 additions and 346 deletions

View File

@ -5,16 +5,17 @@ import com.auth0.jwt.interfaces.DecodedJWT;
import io.dataease.auth.filter.F2CLinkFilter;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.DeLogUtils;
import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs;
import io.dataease.plugins.common.base.domain.PanelLink;
import io.dataease.controller.panel.api.LinkApi;
import io.dataease.controller.request.chart.ChartExtRequest;
import io.dataease.controller.request.panel.link.*;
import io.dataease.dto.panel.link.GenerateDto;
import io.dataease.dto.panel.link.ValidateDto;
import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs;
import io.dataease.plugins.common.base.domain.PanelLink;
import io.dataease.service.chart.ChartViewService;
import io.dataease.service.panel.PanelLinkService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@ -25,6 +26,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@RestController
@ -65,22 +67,32 @@ public class LinkServer implements LinkApi {
@Override
public ValidateDto validate(@RequestBody LinkValidateRequest request) throws Exception {
String link = request.getLink();
link = URLDecoder.decode(link, "UTF-8");
link = URLDecoder.decode(link, StandardCharsets.UTF_8);
String json = panelLinkService.decryptParam(link);
String[] jsonArray = json.split(",");
String uuid = null;
int len = jsonArray.length;
if (len > 1) {
uuid = jsonArray[1];
}
String user = request.getUser();
user = URLDecoder.decode(user, "UTF-8");
user = URLDecoder.decode(user, StandardCharsets.UTF_8);
user = panelLinkService.decryptParam(user);
ValidateDto dto = new ValidateDto();
dto.setUserId(user);
String resourceId = json;
String resourceId = jsonArray[0];
PanelLink one = panelLinkService.findOne(resourceId, Long.valueOf(user));
dto.setResourceId(resourceId);
if (ObjectUtils.isEmpty(one)) {
dto.setValid(false);
return dto;
}
String mappingUuid = panelLinkService.getMappingUuid(one);
if (!StringUtils.equals(uuid, mappingUuid)) {
dto.setValid(false);
return dto;
}
dto.setValid(one.getValid());
dto.setEnablePwd(one.getEnablePwd());
dto.setPassPwd(panelLinkService.validateHeads(one));
@ -94,8 +106,8 @@ public class LinkServer implements LinkApi {
}
@Override
public Object resourceDetail(@PathVariable String resourceId,@PathVariable String userId) {
return panelLinkService.resourceInfo(resourceId,userId);
public Object resourceDetail(@PathVariable String resourceId, @PathVariable String userId) {
return panelLinkService.resourceInfo(resourceId, userId);
}
@Override
@ -125,7 +137,7 @@ public class LinkServer implements LinkApi {
operateType = SysLogConstants.OPERATE_TYPE.MB_VIEW;
}
if (ObjectUtils.isEmpty(userId)) return;
PanelGroupWithBLOBs panelGroupWithBLOBs = panelLinkService.resourceInfo(panelId,String.valueOf(userId));
PanelGroupWithBLOBs panelGroupWithBLOBs = panelLinkService.resourceInfo(panelId, String.valueOf(userId));
String pid = panelGroupWithBLOBs.getPid();
DeLogUtils.save(operateType, SysLogConstants.SOURCE_TYPE.LINK, panelId, pid, userId, SysLogConstants.SOURCE_TYPE.USER);
}

View File

@ -309,7 +309,8 @@
`is_plugin`,
`senior`,
`data_from`,
`view_fields`)
`view_fields`,
`_aggregate`)
SELECT #{newChartId},
GET_CHART_VIEW_COPY_NAME(#{oldChartId}, #{panelId}) as `name`,
#{panelId},
@ -338,7 +339,8 @@
`is_plugin`,
`senior`,
`data_from`,
`view_fields`
`view_fields`,
`_aggregate`
FROM chart_view
WHERE id = #{oldChartId}
</insert>

View File

@ -3,17 +3,15 @@
<mapper namespace="io.dataease.ext.MobileDirMapper">
<select id="query" resultType="io.dataease.mobile.entity.PanelEntity">
SELECT
id,
NAME AS text,
pid,
node_type AS `type`
FROM
panel_group g,
( SELECT GET_V_AUTH_MODEL_ID_P_USE_MOBILE ( #{userId}, 'panel' ) cids ) t
WHERE
g.pid = #{pid}
AND FIND_IN_SET( g.id, cids )
SELECT id,
NAME AS text,
pid,
node_type AS `type`
FROM panel_group g,
(SELECT GET_V_AUTH_MODEL_ID_P_USE_MOBILE(#{userId}, 'panel') cids) t
WHERE g.pid = #{pid}
AND FIND_IN_SET(g.id, cids)
ORDER BY g.panel_sort desc, CONVERT(g.name using gbk)
</select>
<select id="queryWithName" resultType="io.dataease.mobile.entity.PanelEntity">
@ -26,35 +24,34 @@
panel_group g,
( SELECT GET_V_AUTH_MODEL_ID_P_USE_MOBILE ( #{userId}, 'panel' ) cids ) t
WHERE
FIND_IN_SET( g.id, cids )
<if test="name != null">
and name like CONCAT('%', #{name, jdbcType=VARCHAR}, '%')
</if>
FIND_IN_SET( g.id, cids )
<if test="name != null">
and name like CONCAT('%', #{name, jdbcType=VARCHAR}, '%')
</if>
ORDER BY g.panel_sort desc, CONVERT(g.name using gbk)
</select>
<select id="idsWithUser" resultType="java.lang.String">
select a.auth_source
from sys_auth a
left join sys_auth_detail d on a.id = d.auth_id
where
a.auth_target_type = 'user' and
a.auth_target = #{userId} and
a.auth_source_type = 'panel' and
d.privilege_type = 1 and
d.privilege_value = 1
left join sys_auth_detail d on a.id = d.auth_id
where a.auth_target_type = 'user'
and a.auth_target = #{userId}
and a.auth_source_type = 'panel'
and d.privilege_type = 1
and d.privilege_value = 1
</select>
<select id="idsWithDept" resultType="java.lang.String">
select a.auth_source
from sys_auth a
left join sys_auth_detail d on a.id = d.auth_id
where
a.auth_target_type = 'dept' and
a.auth_target = #{deptId} and
a.auth_source_type = 'panel' and
d.privilege_type = 1 and
d.privilege_value = 1
left join sys_auth_detail d on a.id = d.auth_id
where a.auth_target_type = 'dept'
and a.auth_target = #{deptId}
and a.auth_source_type = 'panel'
and d.privilege_type = 1
and d.privilege_value = 1
</select>
<select id="idsWithRoles" resultType="java.lang.String">
@ -62,20 +59,16 @@
from sys_auth a
left join sys_auth_detail d on a.id = d.auth_id
where
a.auth_target_type = 'role' and
a.auth_target in
<foreach collection="roleIds" item="roleId" open='(' separator=',' close=')'>
#{roleId}
</foreach>
and
a.auth_source_type = 'panel' and
d.privilege_type = 1 and
d.privilege_value = 1
a.auth_target_type = 'role' and
a.auth_target in
<foreach collection="roleIds" item="roleId" open='(' separator=',' close=')'>
#{roleId}
</foreach>
and
a.auth_source_type = 'panel' and
d.privilege_type = 1 and
d.privilege_value = 1
</select>
</mapper>

View File

@ -1,6 +1,5 @@
package io.dataease.plugins.server;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
@ -24,6 +23,8 @@ import io.dataease.service.ScheduleService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
@ -35,10 +36,10 @@ import org.springframework.web.util.HtmlUtils;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -340,35 +341,52 @@ public class XEmailTaskServer {
Pager<List<XpackTaskInstanceDTO>> listPager = instancesGrid(0, 0, request);
List<XpackTaskInstanceDTO> instanceDTOS = listPager.getListObject();
ExcelSheetModel excelSheetModel = excelSheetModel(instanceDTOS);
List<ExcelSheetModel> sheetModels = new ArrayList<>();
sheetModels.add(excelSheetModel);
File file = ExcelUtils.exportExcel(sheetModels, null, null);
InputStream inputStream = new FileInputStream(file);
HttpServletResponse response = ServletUtils.response();
OutputStream outputStream = response.getOutputStream();
try {
String filename = file.getName();
response.reset();
response.addHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/octet-stream;charset=UTF-8");
response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
ServletOutputStream outputStream = response.getOutputStream();
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
// 读取文件
bis = new BufferedInputStream(inputStream);
int i = bis.read(buff);
while (i != -1) {
outputStream.write(buff, 0, buff.length);
outputStream.flush();
i = bis.read(buff);
Workbook wb = new SXSSFWorkbook();
Sheet detailsSheet = wb.createSheet(excelSheetModel.getSheetName());
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
//设置字体大小
font.setFontHeightInPoints((short) 12);
//设置字体加粗
font.setBold(true);
//给字体设置样式
cellStyle.setFont(font);
//设置单元格背景颜色
cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
//设置单元格填充样式(使用纯色背景颜色填充)
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
List<List<String>> details = null;
if (CollectionUtils.isNotEmpty(details = excelSheetModel.getData())) {
details.add(0, excelSheetModel.getHeads());
for (int i = 0; i < details.size(); i++) {
Row row = detailsSheet.createRow(i);
List<String> rowData = details.get(i);
if (rowData != null) {
for (int j = 0; j < rowData.size(); j++) {
Cell cell = row.createCell(j);
cell.setCellValue(rowData.get(j));
if (i == 0) {// 头部
detailsSheet.setColumnWidth(j, 255 * 20);
cell.setCellStyle(cellStyle);
}
}
}
}
}
response.setContentType("application/vnd.ms-excel");
//文件名称
String fileName = excelSheetModel.getSheetName();
String encodeFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName + ".xlsx");
wb.write(outputStream);
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (file.exists())
FileUtil.del(file);
} catch (Exception e) {
DataEaseException.throwException(e);
}
}

View File

@ -5,7 +5,6 @@ import com.alibaba.druid.pool.DruidPooledConnection;
import com.google.gson.Gson;
import io.dataease.commons.utils.LogUtil;
import io.dataease.dto.datasource.*;
import io.dataease.i18n.Translator;
import io.dataease.plugins.common.base.domain.Datasource;
import io.dataease.plugins.common.base.domain.DeDriver;
@ -105,6 +104,42 @@ public class JdbcProvider extends DefaultJdbcProvider {
OracleConfiguration oracleConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfiguration.class);
schemaPattern = oracleConfiguration.getSchema();
}
//获取主键
ResultSet primaryKeys = databaseMetaData.getPrimaryKeys(null, schemaPattern, tableNamePattern);
Set<String> primaryKeySet = new HashSet<>();
while (primaryKeys.next()) {
String tableName = primaryKeys.getString("TABLE_NAME");
String database;
String schema = primaryKeys.getString("TABLE_SCHEM");
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name()) || datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.ck.name())
|| datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.impala.name())) {
database = primaryKeys.getString("TABLE_SCHEM");
} else {
database = primaryKeys.getString("TABLE_CAT");
}
//获取主键的名称
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
} else if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest)) && schema.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
} else {
if (database != null) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
}
}
}
ResultSet resultSet = databaseMetaData.getColumns(null, schemaPattern, tableNamePattern, "%");
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
@ -118,23 +153,23 @@ public class JdbcProvider extends DefaultJdbcProvider {
}
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
} else if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest)) && schema.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
} else {
if (database != null) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
TableField tableField = getTableFiled(resultSet, datasourceRequest);
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
}
@ -156,7 +191,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
return list;
}
private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest) throws SQLException {
private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest, Set<String> primaryKeySet) throws SQLException {
TableField tableField = new TableField();
String colName = resultSet.getString("COLUMN_NAME");
tableField.setFieldName(colName);
@ -197,6 +232,14 @@ public class JdbcProvider extends DefaultJdbcProvider {
if (StringUtils.isNotEmpty(tableField.getFieldType()) && tableField.getFieldType().equalsIgnoreCase("DECIMAL")) {
tableField.setAccuracy(Integer.valueOf(resultSet.getString("DECIMAL_DIGITS")));
}
if (primaryKeySet.contains(colName)) {
tableField.setPrimaryKey(true);
}
if (StringUtils.equalsIgnoreCase(resultSet.getString("IS_NULLABLE"), "NO")) {
tableField.setNotNull(true);
}
return tableField;
}
@ -295,7 +338,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
break;
case Types.NUMERIC:
BigDecimal bigDecimal = rs.getBigDecimal(j + 1);
row[j] = bigDecimal == null ? null: bigDecimal.toString();
row[j] = bigDecimal == null ? null : bigDecimal.toString();
break;
default:
if (metaData.getColumnTypeName(j + 1).toLowerCase().equalsIgnoreCase("blob")) {
@ -538,7 +581,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
driverClassName = defaultDriver;
jdbcClassLoader = extendedJdbcClassLoader;
for (DataSourceType value : SpringContextUtil.getApplicationContext().getBeansOfType(DataSourceType.class).values()) {
if(value.getType().equalsIgnoreCase(datasourceRequest.getDatasource().getType())){
if (value.getType().equalsIgnoreCase(datasourceRequest.getDatasource().getType())) {
surpportVersions = value.getSurpportVersions();
}
}
@ -563,10 +606,11 @@ public class JdbcProvider extends DefaultJdbcProvider {
Thread.currentThread().setContextClassLoader(classLoader);
}
if(StringUtils.isNotEmpty(surpportVersions) && surpportVersions.split(",").length > 0){
if(! Arrays.asList(surpportVersions.split(",")).contains(String.valueOf(conn.getMetaData().getDatabaseMajorVersion()))){
if (StringUtils.isNotEmpty(surpportVersions) && surpportVersions.split(",").length > 0) {
if (!Arrays.asList(surpportVersions.split(",")).contains(String.valueOf(conn.getMetaData().getDatabaseMajorVersion()))) {
DataEaseException.throwException("当前驱动不支持此版本!");
};
}
;
}
return conn;
}
@ -698,7 +742,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
throw new Exception(Translator.get("i18n_schema_is_empty"));
}
return "select table_name, owner, comments from all_tab_comments where owner='" + oracleConfiguration.getSchema() + "' AND table_type = 'TABLE'";
case pg:
case pg:
PgConfiguration pgConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfiguration.class);
if (StringUtils.isEmpty(pgConfiguration.getSchema())) {
throw new Exception(Translator.get("i18n_schema_is_empty"));
@ -821,58 +865,58 @@ public class JdbcProvider extends DefaultJdbcProvider {
case StarRocks:
MysqlConfiguration mysqlConfiguration = new Gson().fromJson(datasource.getConfiguration(), MysqlConfiguration.class);
mysqlConfiguration.getJdbc();
if(!mysqlConfiguration.getDataBase().matches("^[ 0-9a-zA-Z_.-]{1,}$")){
if (!mysqlConfiguration.getDataBase().matches("^[ 0-9a-zA-Z_.-]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case redshift:
RedshiftConfiguration redshiftConfiguration = new Gson().fromJson(datasource.getConfiguration(), RedshiftConfiguration.class);
if(redshiftConfiguration.getDataBase().length() > 64 || redshiftConfiguration.getDataBase().length() < 1){
if (redshiftConfiguration.getDataBase().length() > 64 || redshiftConfiguration.getDataBase().length() < 1) {
throw new Exception("Invalid database name");
}
if(!redshiftConfiguration.getDataBase().matches("^[a-z][a-z0-9_+.@-]*$")){
if (!redshiftConfiguration.getDataBase().matches("^[a-z][a-z0-9_+.@-]*$")) {
throw new Exception("Invalid database name");
}
break;
case sqlServer:
SqlServerConfiguration sqlServerConfiguration = new Gson().fromJson(datasource.getConfiguration(), SqlServerConfiguration.class);
if(!sqlServerConfiguration.getDataBase().matches("^[0-9a-zA-Z-_.\u4E00-\u9FA5\u8FBD-\u9FBB\uFA0E-\uFA29\u2e80-\u9fff]{1,}$")){
if (!sqlServerConfiguration.getDataBase().matches("^[0-9a-zA-Z-_.\u4E00-\u9FA5\u8FBD-\u9FBB\uFA0E-\uFA29\u2e80-\u9fff]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case pg:
PgConfiguration pgConfiguration = new Gson().fromJson(datasource.getConfiguration(), PgConfiguration.class);
if(!pgConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){
if (!pgConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case oracle:
OracleConfiguration oracleConfiguration = new Gson().fromJson(datasource.getConfiguration(), OracleConfiguration.class);
if(!oracleConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$") && !oracleConfiguration.getConnectionType().equalsIgnoreCase("serviceName")){
if (!oracleConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$") && !oracleConfiguration.getConnectionType().equalsIgnoreCase("serviceName")) {
throw new Exception("Invalid database name");
}
break;
case mongo:
MongodbConfiguration mongodbConfiguration = new Gson().fromJson(datasource.getConfiguration(), MongodbConfiguration.class);
if(!mongodbConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){
if (!mongodbConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case impala:
ImpalaConfiguration impalaConfiguration = new Gson().fromJson(datasource.getConfiguration(), ImpalaConfiguration.class);
if(!impalaConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){
if (!impalaConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case hive:
HiveConfiguration hiveConfiguration = new Gson().fromJson(datasource.getConfiguration(), HiveConfiguration.class);
if(!hiveConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){
if (!hiveConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) {
throw new Exception("Invalid database name");
}
break;
case db2:
Db2Configuration db2Configuration = new Gson().fromJson(datasource.getConfiguration(), Db2Configuration.class);
if(!db2Configuration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){
if (!db2Configuration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) {
throw new Exception("Invalid database name");
}
break;

View File

@ -439,10 +439,10 @@ public class SqlserverQueryProvider extends QueryProvider {
@Override
public String getSQLTableInfo(String table, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) {
return originTableInfo(table, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, true);
return originTableInfo(table, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, true, false);
}
public String originTableInfo(String table, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean needResultCount) {
public String originTableInfo(String table, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean needResultCount, boolean ignoreOrder) {
SQLObj tableObj = SQLObj.builder()
.tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table))
.tableAlias(String.format(TABLE_ALIAS_PREFIX, 0))
@ -496,13 +496,15 @@ public class SqlserverQueryProvider extends QueryProvider {
groups.addAll(xFields);
// 外层再次套sql
List<SQLObj> orders = new ArrayList<>();
orders.addAll(xOrders);
if (needOrder && CollectionUtils.isEmpty(xOrders)) {
orders.add(SQLObj.builder()
.orderField(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0))
.orderAlias(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0))
.orderDirection("ASC")
.build());
if (!ignoreOrder) {
orders.addAll(xOrders);
if (needOrder && CollectionUtils.isEmpty(xOrders)) {
orders.add(SQLObj.builder()
.orderField(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0))
.orderAlias(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0))
.orderDirection("ASC")
.build());
}
}
STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE);
@ -528,8 +530,8 @@ public class SqlserverQueryProvider extends QueryProvider {
return st.render();
}
public String originSQLAsTmpTableInfo(String sql, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder) {
return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, null, view, needOrder, true);
public String originSQLAsTmpTableInfo(String sql, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean ignoreOrder) {
return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, null, view, needOrder, true, ignoreOrder);
}
public String getSQLWithPage(boolean isTable, String sql, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, PageInfo pageInfo) {
@ -543,9 +545,9 @@ public class SqlserverQueryProvider extends QueryProvider {
boolean isPage = (pageInfo.getGoPage() != null && pageInfo.getPageSize() != null);
String limit = (isPage ? " OFFSET " + (pageInfo.getGoPage() - 1) * pageInfo.getPageSize() + " ROW FETCH NEXT " + pageInfo.getPageSize() + " ROW ONLY " : "");
if (isTable) {
return originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage) + limit;
return originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage, false) + limit;
} else {
return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage) + limit;
return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage, false) + limit;
}
}
}
@ -1790,9 +1792,9 @@ public class SqlserverQueryProvider extends QueryProvider {
@Override
public String getResultCount(boolean isTable, String sql, List<ChartViewFieldDTO> xAxis, FilterTreeObj fieldCustomFilter, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, List<ChartExtFilterRequest> extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) {
if (isTable) {
return "SELECT COUNT(*) AS count from (" + originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true) + ") COUNT_TEMP";
return "SELECT COUNT(*) AS count from (" + originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true, true) + ") COUNT_TEMP";
} else {
return "SELECT COUNT(*) AS count from (" + originSQLAsTmpTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false) + ") COUNT_TEMP";
return "SELECT COUNT(*) AS count from (" + originSQLAsTmpTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true) + ") COUNT_TEMP";
}
}
}

View File

@ -1058,9 +1058,10 @@ public class ChartViewService {
});
xAxis.addAll(xAxisExtList);
}
fieldMap.put("xAxis", xAxis);
fieldMap.put("xAxisExt", xAxisExt);
fieldMap.put("extStack", extStack);
fieldMap.put("extBubble", extBubble);
fieldMap.put("xAxis", xAxis);
fieldMap.put("yAxis", yAxis);
PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view, rowPermissionsTree, chartExtRequest);
String sql = pluginViewSql(pluginViewParam, view);

View File

@ -1087,6 +1087,7 @@ public class ChartDataBuild {
List<ChartViewFieldDTO> fields = new ArrayList<>();
List<ChartViewFieldDTO> yfields = new ArrayList<>();
if (CollectionUtils.isNotEmpty(fieldMap.get("xAxis"))) fields.addAll(fieldMap.get("xAxis"));
if (CollectionUtils.isNotEmpty(fieldMap.get("xAxisExt"))) fields.addAll(fieldMap.get("xAxisExt"));
for (Map.Entry<String, List<ChartViewFieldDTO>> entry : fieldMap.entrySet()) {
if (StringUtils.equalsAny(entry.getKey(), keys)) {

View File

@ -226,6 +226,7 @@ public class ExtractDataService {
toDelete.forEach(datasetTableField -> dataSetTableFieldsService.delete(datasetTableField.getId()));
}
} catch (Exception e) {
e.printStackTrace();
saveErrorLog(datasetTableTaskLog, e, false);
updateTableStatus(datasetTableId, JobStatus.Error, null);
dropDorisTable(TableUtils.tmpName(TableUtils.tableName(datasetTableId)));
@ -1294,14 +1295,14 @@ public class ExtractDataService {
UserDefinedJavaClassMeta userDefinedJavaClassMeta = new UserDefinedJavaClassMeta();
List<UserDefinedJavaClassMeta.FieldInfo> fields = new ArrayList<>();
if (isSetKey) {
if (!isSetKey) {
UserDefinedJavaClassMeta.FieldInfo fieldInfo = new UserDefinedJavaClassMeta.FieldInfo("dataease_uuid", ValueMetaInterface.TYPE_STRING, -1, -1);
fields.add(fieldInfo);
}
userDefinedJavaClassMeta.setFieldInfo(fields);
List<UserDefinedJavaClassDef> definitions = new ArrayList<>();
String tmp_code = code.replace("handleWraps", handleWraps).replace("handleBinaryType", handleBinaryTypeCode.toString());
if (isSetKey) {
if (!isSetKey) {
tmp_code = tmp_code.replace("handleDataease_uuid", "");
} else {
tmp_code = tmp_code.replace("handleDataease_uuid", handleDataease_uuid);

View File

@ -4,7 +4,10 @@ import io.dataease.auth.config.RsaProperties;
import io.dataease.auth.util.JWTUtils;
import io.dataease.auth.util.RsaUtil;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.*;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.CodingUtil;
import io.dataease.commons.utils.DeLogUtils;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.controller.request.panel.link.EnablePwdRequest;
import io.dataease.controller.request.panel.link.LinkRequest;
import io.dataease.controller.request.panel.link.OverTimeRequest;
@ -127,6 +130,16 @@ public class PanelLinkService {
}
}
public String getMappingUuid(PanelLink link) {
String resourceId = link.getResourceId();
Long userId = link.getUserId();
PanelLinkMappingExample example = new PanelLinkMappingExample();
example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(userId);
List<PanelLinkMapping> mappings = panelLinkMappingMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(mappings)) return mappings.get(0).getUuid();
return null;
}
@Transactional
public GenerateDto currentGenerate(String resourceId) {
PanelLink one = findOne(resourceId, AuthUtils.getUser().getUserId());
@ -143,14 +156,17 @@ public class PanelLinkService {
PanelLinkMappingExample example = new PanelLinkMappingExample();
example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(AuthUtils.getUser().getUserId());
List<PanelLinkMapping> mappings = panelLinkMappingMapper.selectByExample(example);
PanelLinkMapping mapping = null;
if (CollectionUtils.isEmpty(mappings)) {
PanelLinkMapping mapping = new PanelLinkMapping();
mapping = new PanelLinkMapping();
mapping.setResourceId(resourceId);
mapping.setUserId(AuthUtils.getUser().getUserId());
mapping.setUuid(CodingUtil.shortUuid());
panelLinkMappingMapper.insert(mapping);
} else {
mapping = mappings.get(0);
}
return convertDto(one);
return convertDto(one, mapping.getUuid());
}
public void deleteByResourceId(String resourceId) {
@ -177,20 +193,24 @@ public class PanelLinkService {
return null;
}
private String buildLinkParam(PanelLink link) {
String linkParam = encrypt(link.getResourceId());
private String buildLinkParam(PanelLink link, String uuid) {
String resourceId = link.getResourceId();
if (StringUtils.isNotBlank(uuid)) {
resourceId += ("," + uuid);
}
String linkParam = encrypt(resourceId);
if (link.getUserId() != null) {
linkParam = linkParam + USERPARAM + encrypt(link.getUserId().toString());
}
return linkParam;
}
private GenerateDto convertDto(PanelLink link) {
private GenerateDto convertDto(PanelLink link, String uuid) {
GenerateDto result = new GenerateDto();
result.setValid(link.getValid());
result.setEnablePwd(link.getEnablePwd());
result.setPwd(link.getPwd());
result.setUri(BASEURL + buildLinkParam(link));
result.setUri(BASEURL + buildLinkParam(link, uuid));
result.setOverTime(link.getOverTime());
return result;
}
@ -237,8 +257,8 @@ public class PanelLinkService {
return pass;
}
public PanelGroupDTO resourceInfo(String resourceId,String userId) {
PanelGroupDTO result = extPanelGroupMapper.findOneWithPrivileges(resourceId,userId);
public PanelGroupDTO resourceInfo(String resourceId, String userId) {
PanelGroupDTO result = extPanelGroupMapper.findOneWithPrivileges(resourceId, userId);
result.setWatermarkInfo(panelWatermarkMapper.selectByPrimaryKey("system_default"));
return result;
}
@ -261,7 +281,7 @@ public class PanelLinkService {
if (StringUtils.isNotBlank(mapping.getUuid())) {
one.setResourceId("error-resource-id");
}
return convertDto(one).getUri();
return convertDto(one, mapping.getUuid()).getUri();
}
public String getUrlByUuid(String uuid) {
@ -271,12 +291,12 @@ public class PanelLinkService {
if (CollectionUtils.isEmpty(mappings)) {
PanelLink panelLink = new PanelLink();
panelLink.setResourceId("error-resource-id");
return BASEURL + buildLinkParam(panelLink);
return BASEURL + buildLinkParam(panelLink, null);
}
PanelLinkMapping mapping = mappings.get(0);
String resourceId = mapping.getResourceId();
Long userId = mapping.getUserId();
PanelLink one = findOne(resourceId, userId);
return convertDto(one).getUri();
return convertDto(one, uuid).getUri();
}
}

View File

@ -1,9 +1,12 @@
ALTER TABLE `datasource`
ALTER TABLE `datasource`
ADD COLUMN `version` varchar(255) NULL COMMENT '版本' AFTER `status`;
ALTER TABLE `sys_auth`
MODIFY COLUMN `auth_details` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '授权明细' AFTER `auth_time`;
ALTER TABLE `sys_auth`
MODIFY COLUMN `auth_details` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '授权明细' AFTER `auth_time`;
ALTER TABLE `sys_auth_detail`
MODIFY COLUMN `privilege_type` int(6) NULL DEFAULT NULL COMMENT '权限类型1 使用/查看 3 导出/管理 5 仪表板管理 15 授权' AFTER `privilege_name`,
MODIFY COLUMN `privilege_value` int(6) NULL DEFAULT NULL COMMENT '权限值1 可用 0 不可用' AFTER `privilege_type`;
ALTER TABLE `sys_auth_detail`
MODIFY COLUMN `privilege_type` int(6) NULL DEFAULT NULL COMMENT '权限类型1 使用/查看 3 导出/管理 5 仪表板管理 15 授权' AFTER `privilege_name`,
MODIFY COLUMN `privilege_value` int(6) NULL DEFAULT NULL COMMENT '权限值1 可用 0 不可用' AFTER `privilege_type`;
ALTER TABLE `sys_task_email`
MODIFY COLUMN `groups` longtext NULL COMMENT '群聊' AFTER `view_data_range`;

View File

@ -1,6 +1,6 @@
{
"name": "dataease",
"version": "1.18.14",
"version": "1.18.15",
"description": "dataease front",
"private": true,
"scripts": {

View File

@ -9,7 +9,7 @@
v-if="isPublicLink"
ref="widget-div"
class="function-div"
:class="functionClass"
:class="[{['function-back-div']: backToTopBtn},functionClass]"
>
<el-button-group size="mini">
<el-button
@ -39,8 +39,8 @@
icon-class="link-down"
/>{{ $t('panel.down') }}</span></el-button>
<el-button
id="fullscreenElement"
v-if="isPcTerminal"
id="fullscreenElement"
size="mini"
@click="toggleFullscreen"
>
@ -48,15 +48,8 @@
style="width: 12px;height: 12px"
:icon-class="fullscreenState?'public_fullscreen_exit':'public_fullscreen'"
/>{{ fullscreenState?$t('panel.fullscreen_exit'): $t('panel.fullscreen_preview') }}</span></el-button>
<el-button
v-show="backToTopBtn"
size="mini"
type="warning"
@click="backToTop"
><i class="icon iconfont icon-back-top" />{{ $t('panel.back_to_top') }}</el-button>
</el-button-group>
</div>
<div
v-else-if="existLinkage || backToTopBtn"
class="bar-main-right"
@ -75,6 +68,16 @@
@click="backToTop"
><i class="icon iconfont icon-back-top" />{{ $t('panel.back_to_top') }}</el-button>
</div>
<div
v-show="isPublicLink && backToTopBtn"
class="link-public"
>
<el-button
size="mini"
type="warning"
@click="backToTop"
><i class="icon iconfont icon-back-top" />{{ $t('panel.back_to_top') }}</el-button>
</div>
</div>
</template>
@ -106,7 +109,7 @@ export default {
},
computed: {
isPcTerminal() {
return this.terminal === 'PC'
return this.terminal === 'pc'
},
functionClass() {
let result = 'function-light'
@ -131,7 +134,7 @@ export default {
return this.$route.query.fromLink === 'true'
},
containerClass() {
return this.isPublicLink ? 'trans-pc' : 'bar-main'
return this.isPublicLink && this.isPcTerminal ? 'trans-pc' : 'bar-main'
},
...mapState([
'componentData'
@ -293,4 +296,14 @@ export default {
}
}
.link-public {
top: -49px;
right: 8px;
opacity: 0.8;
position: absolute;
}
.function-back-div {
right: 100px!important;
}
</style>

View File

@ -116,15 +116,39 @@
v-if="chartDetailsVisible"
style="position: absolute;right: 70px;top:15px"
>
<el-button
v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && showChartInfo.type !== 'symbol-map'"
class="el-icon-picture-outline"
size="mini"
:disabled="imageDownloading"
@click="exportViewImg"
>
{{ $t('chart.export_img') }}
</el-button>
<span v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && showChartInfo.type !== 'symbol-map'">
<span style="font-size: 12px">
导出分辨率
</span>
<el-select
v-model="pixel"
style="width: 120px; margin-right: 8px; margin-top: -1px"
:popper-append-to-body="false"
size="mini"
>
<el-option-group
v-for="group in pixelOptions"
:key="group.label"
:label="group.label"
>
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-option-group>
</el-select>
<el-button
class="el-icon-picture-outline"
size="mini"
:disabled="imageDownloading"
@click="exportViewImg"
>
{{ $t('chart.export_img') }}
</el-button>
</span>
<el-button
v-if="showChartInfoType==='details'&& hasDataPermission('export',panelInfo.privileges)"
size="mini"
@ -293,7 +317,44 @@ export default {
pdfTemplateSelectedIndex: 0,
pdfTemplateContent: '',
templateInfo: {},
pdfTemplateAll: []
pdfTemplateAll: [],
pixelOptions: [
{
label: 'Windows(16:9)',
options: [
{
value: '1920 * 1080',
label: '1920 * 1080'
},
{
value: '1600 * 900',
label: '1600 * 900'
},
{
value: '1280 * 720',
label: '1280 * 720'
}
]
},
{
label: 'MacOS(16:10)',
options: [
{
value: '2560 * 1600',
label: '2560 * 1600'
},
{
value: '1920 * 1200',
label: '1920 * 1200'
},
{
value: '1680 * 1050',
label: '1680 * 1050'
}
]
}
],
pixel: '1280 * 720'
}
},
computed: {
@ -764,7 +825,7 @@ export default {
},
exportViewImg() {
this.imageDownloading = true
this.$refs['userViewDialog-canvas-main'].exportViewImg(() => {
this.$refs['userViewDialog-canvas-main'].exportViewImg(this.pixel, () => {
this.imageDownloading = false
})
},
@ -785,6 +846,7 @@ export default {
canvasScroll() {
// 100px
this.backToTopBtnShow = this.$refs[this.previewOutRefId].scrollTop > 200
console.log('top=' + this.$refs[this.previewOutRefId].scrollTop + ';this.backToTopBtnShow=' + this.backToTopBtnShow)
bus.$emit('onScroll')
},
initListen() {

View File

@ -175,7 +175,8 @@ export default {
const range = document.createRange()
const sel = window.getSelection()
if (myDiv.childNodes) {
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1)
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1]
.childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1], 1)
range.collapse(false)
sel.removeAllRanges()
sel.addRange(range)

View File

@ -250,7 +250,9 @@ export default {
const range = document.createRange()
const sel = window.getSelection()
if (myDiv.childNodes) {
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1)
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1]
.childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1],
myDiv.childNodes[myDiv.childNodes.length - 1].childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1].length)
range.collapse(false)
sel.removeAllRanges()
sel.addRange(range)

View File

@ -154,15 +154,39 @@
v-if="chartDetailsVisible"
style="position: absolute;right: 70px;top:15px"
>
<el-button
v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && !equalsAny(showChartInfo.type, 'symbol-map', 'flow-map')"
class="el-icon-picture-outline"
size="mini"
:disabled="imageDownloading"
@click="exportViewImg"
>
{{ $t('chart.export_img') }}
</el-button>
<span v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && !equalsAny(showChartInfo.type, 'symbol-map', 'flow-map')">
<span style="font-size: 12px">
导出分辨率
</span>
<el-select
v-model="pixel"
style="width: 120px; margin-right: 8px; margin-top: -1px"
:popper-append-to-body="false"
size="mini"
>
<el-option-group
v-for="group in pixelOptions"
:key="group.label"
:label="group.label"
>
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-option-group>
</el-select>
<el-button
class="el-icon-picture-outline"
size="mini"
:disabled="imageDownloading"
@click="exportViewImg"
>
{{ $t('chart.export_img') }}
</el-button>
</span>
<el-button
v-if="showChartInfoType==='details' && hasDataPermission('export',panelInfo.privileges)"
size="mini"
@ -367,7 +391,44 @@ export default {
show: 0
},
view: {},
cancelTime: null
cancelTime: null,
pixelOptions: [
{
label: 'Windows(16:9)',
options: [
{
value: '1920 * 1080',
label: '1920 * 1080'
},
{
value: '1600 * 900',
label: '1600 * 900'
},
{
value: '1280 * 720',
label: '1280 * 720'
}
]
},
{
label: 'MacOS(16:10)',
options: [
{
value: '2560 * 1600',
label: '2560 * 1600'
},
{
value: '1920 * 1200',
label: '1920 * 1200'
},
{
value: '1680 * 1050',
label: '1680 * 1050'
}
]
}
],
pixel: '1280 * 720'
}
},
@ -685,7 +746,7 @@ export default {
},
exportViewImg() {
this.imageDownloading = true
this.$refs['userViewDialog'].exportViewImg(() => {
this.$refs['userViewDialog'].exportViewImg(this.pixel,() => {
this.imageDownloading = false
})
},
@ -1110,7 +1171,7 @@ export default {
}
})
}
if (!jumpInfo) {
if (!jumpInfo && !this.chart.type.includes('table')) {
for (let i = param.dimensionList.length - 1; i >= 0; i--) {
dimension = param.dimensionList[i]
sourceInfo = param.viewId + '#' + dimension.id

View File

@ -13,7 +13,6 @@
>
<div
id="chartCanvas"
:class="{'canvas-class-exporting':exporting}"
class="canvas-class"
:style="customStyle"
>
@ -23,6 +22,7 @@
>
<plugin-com
v-if="chart.isPlugin"
:ref="element.propValue.id"
:component-name="chart.type + '-view'"
:obj="{chart: mapChart || chart}"
:chart="mapChart || chart"
@ -31,32 +31,38 @@
class="chart-class"
/>
<chart-component
:ref="element.propValue.id"
v-else-if="!chart.type.includes('text') && chart.type !== 'label' && !chart.type.includes('table') && renderComponent() === 'echarts'"
:theme-style="element.commonBackground"
class="chart-class"
:chart="mapChart || chart"
/>
<chart-component-g2
:ref="element.propValue.id"
v-else-if="!chart.type.includes('text') && chart.type !== 'label' && !chart.type.includes('table') && renderComponent() === 'antv'"
class="chart-class show-in-dialog"
:chart="chart"
/>
<chart-component-s2
:ref="element.propValue.id"
v-else-if="chart.type.includes('table') && renderComponent() === 'antv'"
class="chart-class"
:chart="chart"
/>
<label-normal
:ref="element.propValue.id"
v-else-if="chart.type.includes('text')"
:chart="chart"
class="table-class"
/>
<label-normal-text
:ref="element.propValue.id"
v-else-if="chart.type === 'label'"
:chart="chart"
class="table-class"
/>
<table-normal
:ref="element.propValue.id"
v-else-if="chart.type.includes('table') && renderComponent() === 'echarts'"
:chart="chart"
class="table-class"
@ -126,7 +132,8 @@ export default {
lastMapChart: null,
linkLoading: false,
exporting: false,
exportLoading: false
exportLoading: false,
pixel: '1280 * 720'
}
},
computed: {
@ -144,6 +151,13 @@ export default {
},
customStyle() {
let style = {}
if (this.exporting) {
const bashStyle = this.pixel.split(' * ')
style = {
width: bashStyle[0] + 'px!important',
height: bashStyle[1] + 'px!important'
}
}
if (this.canvasStyleData.openCommonStyle) {
if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) {
style = {
@ -261,13 +275,16 @@ export default {
}
}
},
exportViewImg(callback) {
exportViewImg(pixel, callback) {
this.pixel = pixel
this.exportLoading = true
this.$nextTick(() => {
this.exporting = true
this.resizeChart()
setTimeout(() => {
exportImg(this.chart.name, (params) => {
this.exporting = false
this.resizeChart()
setTimeout(() => {
this.exportLoading = false
}, 500)
@ -286,6 +303,13 @@ export default {
renderComponent() {
return this.chart.render
},
resizeChart() {
if (this.$refs[this.element.propValue.id]) {
this.chart.isPlugin
? this.$refs[this.element.propValue.id].callPluginInner({ methodName: 'chartResize' })
: this.$refs[this.element.propValue.id].chartResize()
}
}
}
}
@ -320,8 +344,8 @@ export default {
background-size: 100% 100% !important;
}
.canvas-class-exporting {
width: 1080px!important;
height: 560px!important;
width: 1980px!important;
height: 860px!important;
}
.abs-container {

View File

@ -226,6 +226,11 @@ export function checkViewTitle(opt, id, tile) {
export function exportImg(imgName, callback) {
const canvasID = document.getElementById('chartCanvas')
const a = document.createElement('a')
// 保存原始的设备像素比值
const originalDPR = window.devicePixelRatio
// 将设备像素比设置为1
window.devicePixelRatio = 1
html2canvas(canvasID).then(canvas => {
const dom = document.body.appendChild(canvas)
dom.style.display = 'none'
@ -238,8 +243,10 @@ export function exportImg(imgName, callback) {
a.click()
URL.revokeObjectURL(blob)
document.body.removeChild(a)
window.devicePixelRatio = originalDPR
callback()
}).catch(() => {
window.devicePixelRatio = originalDPR
callback()
})
}

View File

@ -554,6 +554,7 @@ export default {
if (this.isCustomSortWidget && this.element.options.attrs?.sort?.sort === 'custom') {
tempData = mergeCustomSortOption(this.element.options.attrs.sort.list, tempData)
}
this.filterInvalidValue(tempData)
return tempData.map(item => {
return {
id: item,
@ -561,6 +562,20 @@ export default {
}
})
},
filterInvalidValue(data) {
if (this.value === null) {
return
}
if (!data.length) {
this.value = null
return
}
if (this.element.options.attrs.multiple) {
this.value = this.value.filter(item => data.includes(item))
} else {
this.value = data.includes(this.value) ? this.value : null
}
},
setOptionWidth(event) {
this.onFocus = true
//

View File

@ -382,6 +382,7 @@ export default {
thumbnail: 'thumbnail',
confirm_delete: 'Confirm delete',
delete_this_dashboard: 'Are you sure to delete this dashboard?',
cancel_this_dashboard: 'Are you sure to cancel this default dashboard?',
delete_this_folder: 'Are you sure to delete this folder?',
confirm_stop: 'Confirm stop',
stop_success: 'Stop success',
@ -840,6 +841,7 @@ export default {
empty_msg: 'If empty then default value is 30 days',
front_error: 'Valid range [0 - 300]', // 修改了提示信息
msg_error: 'Valid range [1 - 365]',
log_live_time_error: 'Valid range [1 - 4000]',
limit_times_error: 'Valid range [1 - 100]',
relieve_times_error: 'Valid range [1 - 100]',
SMTP_port: 'SMTP Port',

View File

@ -382,6 +382,7 @@ export default {
thumbnail: '縮略圖',
confirm_delete: '確認刪除',
delete_this_dashboard: '確認删除該儀錶板嗎?',
cancel_this_dashboard: '確認取消該默认儀錶板嗎?',
delete_this_folder: '確認删除該目錄嗎?',
confirm_stop: '確認停止',
stop_success: '停止成功',
@ -839,6 +840,7 @@ export default {
empty_msg: '為空則默認取值30天',
front_error: '請填寫0-300正整數', // 修改了提示信息
msg_error: '請填寫1-365正整數',
log_live_time_error: '請填寫1-4000正整數',
limit_times_error: '請填寫1-100正整數',
relieve_times_error: '請填寫1-100正整數',
SMTP_port: 'SMTP端口',

View File

@ -381,6 +381,7 @@ export default {
thumbnail: '缩略图',
confirm_delete: '确认删除',
delete_this_dashboard: '确认删除该仪表板吗?',
cancel_this_dashboard: '确认取消该默认仪表板吗?',
delete_this_folder: '确认删除该目录吗?',
confirm_stop: '确认停止',
stop_success: '停止成功',
@ -934,7 +935,8 @@ export default {
edit_classification: '编辑分类',
classification_name: '分类名称',
by_event_details: '通过事件详情搜索',
password_input_error: '原始密码输入错误'
password_input_error: '原始密码输入错误',
log_live_time_error: '请填写1-4000整数'
},
chart: {
empty_hide: '隐藏空值',

View File

@ -32,7 +32,9 @@ import '@/utils/DateUtil'
import draggable from 'vuedraggable'
import deWebsocket from '@/websocket'
import { GaodeMap } from '@antv/l7-maps'
import { Mix } from '@antv/g2plot'
import * as echarts from 'echarts'
import { clear } from 'size-sensor'
import UmyUi from 'umy-ui'
// 全屏插件
import fullscreen from 'vue-fullscreen'
@ -58,6 +60,8 @@ Vue.prototype.$api = api
Vue.prototype.$echarts = echarts
Vue.prototype.$gaodeMap = GaodeMap
Vue.prototype.$Mix = Mix
Vue.prototype.$G2SizeSensorClear = clear
Vue.use(UmyUi)

View File

@ -31,6 +31,8 @@ import '@/utils/DateUtil'
import draggable from 'vuedraggable'
import deWebsocket from '@/websocket'
import { GaodeMap } from '@antv/l7-maps'
import { Mix } from '@antv/g2plot'
import { clear } from 'size-sensor'
import * as echarts from 'echarts'
import UmyUi from 'umy-ui'
// 全屏插件
@ -57,6 +59,8 @@ Vue.prototype.$api = api
Vue.prototype.$echarts = echarts
Vue.prototype.$gaodeMap = GaodeMap
Vue.prototype.$Mix = Mix
Vue.prototype.$G2SizeSensorClear = clear
Vue.use(UmyUi)

View File

@ -55,9 +55,9 @@
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe667;</span>
<span class="icon iconfont">&#xe63f;</span>
<div class="name">返回顶部</div>
<div class="code-name">&amp;#xe667;</div>
<div class="code-name">&amp;#xe63f;</div>
</li>
<li class="dib">
@ -828,9 +828,9 @@
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1705486315942') format('woff2'),
url('iconfont.woff?t=1705486315942') format('woff'),
url('iconfont.ttf?t=1705486315942') format('truetype');
src: url('iconfont.woff2?t=1706079293312') format('woff2'),
url('iconfont.woff?t=1706079293312') format('woff'),
url('iconfont.ttf?t=1706079293312') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2459092 */
src: url('iconfont.woff2?t=1705486315942') format('woff2'),
url('iconfont.woff?t=1705486315942') format('woff'),
url('iconfont.ttf?t=1705486315942') format('truetype');
src: url('iconfont.woff2?t=1706079293312') format('woff2'),
url('iconfont.woff?t=1706079293312') format('woff'),
url('iconfont.ttf?t=1706079293312') format('truetype');
}
.iconfont {
@ -14,7 +14,7 @@
}
.icon-back-top:before {
content: "\e667";
content: "\e63f";
}
.icon-adaptor:before {

File diff suppressed because one or more lines are too long

View File

@ -6,11 +6,11 @@
"description": "",
"glyphs": [
{
"icon_id": "831197",
"icon_id": "8224825",
"name": "返回顶部",
"font_class": "back-top",
"unicode": "e667",
"unicode_decimal": 58983
"unicode": "e63f",
"unicode_decimal": 58943
},
{
"icon_id": "34289857",

View File

@ -170,7 +170,7 @@ div:focus {
padding-right: 50px !important;
}
.de-tabs {
.de-tabs-component {
.el-tabs__header {
margin: 0 0 0 0 !important;
}
@ -1765,4 +1765,4 @@ div:focus {
.el-table__fixed-right::before {
display: none;
}
}

View File

@ -296,6 +296,11 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) {
// config
const slider = getSlider(chart)
const analyse = getAnalyse(chart)
data.forEach(d => {
d.tempId = (Math.random() * 10000000).toString()
})
// options
const options = {
theme: theme,
@ -364,7 +369,9 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) {
type: 'time',
min: minTime,
max: maxTime,
mask: 'YYYY-MM-DD HH:mm:ss',
mask: 'YYYY-MM-DD HH:mm:ss'
},
tempId: {
key: true
}
}
@ -373,7 +380,9 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) {
values: {
min: minNumber,
max: maxNumber,
mask: 'YYYY-MM-DD HH:mm:ss',
mask: 'YYYY-MM-DD HH:mm:ss'
},
tempId: {
key: true
}
}

View File

@ -1,20 +1,9 @@
import { TableSheet, BaseEvent, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE } from '@antv/s2'
import { TableSheet, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE } from '@antv/s2'
import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table'
import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import { handleTableEmptyStrategy, hexColorToRGBA } from '@/views/chart/chart/util'
import { maxBy, minBy } from 'lodash'
class RowHoverInteraction extends BaseEvent {
bindEvents() {
this.spreadsheet.on(S2Event.ROW_CELL_HOVER, (event) => {
this.spreadsheet.tooltip.show({
position: { x: 0, y: 0 },
content: '...'
})
})
}
}
import { maxBy, minBy, find } from 'lodash-es'
export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) {
const containerDom = document.getElementById(container)
@ -152,7 +141,7 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo)
s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event))
}
if (size.tableCellTooltip?.show) {
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event))
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta))
}
// theme
const customTheme = getCustomTheme(chart)
@ -343,7 +332,7 @@ export function baseTableNormal(s2, container, chart, action, tableData) {
s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event))
}
if (size.tableCellTooltip?.show) {
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event))
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta))
}
// theme
const customTheme = getCustomTheme(chart)
@ -562,7 +551,7 @@ export function baseTablePivot(s2, container, chart, action, headerAction, table
s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event, fieldMap))
}
if (size.tableCellTooltip?.show) {
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event))
s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta))
}
// theme
const customTheme = getCustomTheme(chart)
@ -821,9 +810,14 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData)
return color
}
function showTooltipValue(s2Instance, event) {
function showTooltipValue(s2Instance, event, meta) {
const cell = s2Instance.getCell(event.target)
const content = cell.actualText
const valueField = cell.getMeta().valueField
const value = cell.getMeta().data[valueField]
const metaObj = find(meta, m =>
m.field === valueField
)
const content = metaObj.formatter(value)
s2Instance.showTooltip({
position: {
x: event.clientX,

View File

@ -56,6 +56,7 @@
<el-select
v-model="rowTotalItem.dataeaseName"
:placeholder="$t('chart.aggregation')"
popper-class="total-select"
size="mini"
@change="changeTotal(rowTotalItem, totalForm.row.calcTotals.cfg)"
>
@ -74,6 +75,7 @@
<el-select
v-model="rowTotalItem.aggregation"
:placeholder="$t('chart.aggregation')"
popper-class="total-select"
size="mini"
@change="changeTotalAggr(rowTotalItem, totalForm.row.calcTotals.cfg, 'row')"
>
@ -108,6 +110,7 @@
<el-select
v-model="totalForm.row.totalSortField"
class="form-item-select"
popper-class="total-select"
:placeholder="$t('chart.total_sort_field')"
size="mini"
@change="changeTotalCfg('row')"
@ -171,6 +174,7 @@
:disabled="rowNum < 2"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotal(rowSubTotalItem, totalForm.row.calcSubTotals.cfg)"
>
<el-option
@ -190,6 +194,7 @@
:disabled="rowNum < 2"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotalAggr(rowSubTotalItem, totalForm.row.calcSubTotals.cfg, 'row')"
>
<el-option
@ -253,6 +258,7 @@
v-model="colTotalItem.dataeaseName"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotal(colTotalItem, totalForm.col.calcTotals.cfg)"
>
<el-option
@ -271,6 +277,7 @@
v-model="colTotalItem.aggregation"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotalAggr(colTotalItem, totalForm.col.calcTotals.cfg, 'col')"
>
<el-option
@ -304,6 +311,7 @@
<el-select
v-model="totalForm.col.totalSortField"
class="form-item-select"
popper-class="total-select"
:placeholder="$t('chart.total_sort_field')"
size="mini"
@change="changeTotalCfg('col')"
@ -367,6 +375,7 @@
:disabled="colNum < 2"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotal(colSubTotalItem, totalForm.col.calcSubTotals.cfg)"
>
<el-option
@ -386,6 +395,7 @@
:disabled="colNum < 2"
:placeholder="$t('chart.aggregation')"
size="mini"
popper-class="total-select"
@change="changeTotalAggr(colSubTotalItem, totalForm.col.calcSubTotals.cfg, 'col')"
>
<el-option
@ -631,7 +641,11 @@ export default {
}
}
</script>
<style>
.total-select .el-select-dropdown__item {
font-size: 12px;
}
</style>
<style scoped>
.shape-item{
padding: 6px;

View File

@ -851,8 +851,9 @@ export default {
},
delete(data) {
const title = data.source ? 'commons.cancel_this_dashboard':(data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard')
const params = {
title: data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard',
title: title,
type: 'danger',
cb: () => {
delGroup(data.id).then((response) => {

View File

@ -86,7 +86,7 @@
<el-form-item
:label="$t('system_parameter_setting.ds_sync_log_retention_time')"
prop="logTimeOut"
prop="dsSyncLogTimeOut"
>
<el-input
v-model="formInline.dsSyncLogTimeOut"
@ -291,8 +291,8 @@ export default {
],
logTimeOut: [
{
pattern: '^([1-9]|[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-5])$',
message: this.$t('system_parameter_setting.msg_error'),
pattern: /^(?:[1-9]|[1-9]\d{1,2}|[1-3]\d{3}|4000)$/,
message: this.$t('system_parameter_setting.log_live_time_error'),
trigger: 'blur'
}
],

View File

@ -1,6 +1,6 @@
{
"name": "dataease-mobile",
"version": "1.18.14",
"version": "1.18.15",
"private": true,
"scripts": {
"serve": "npm run dev:h5",

View File

@ -1,4 +1,5 @@
const webpack = require('webpack')
const CompressionPlugin = require('compression-webpack-plugin');
const path = require('path')
const utils = require('./utils')
const CopyPlugin = require("copy-webpack-plugin");
@ -93,5 +94,8 @@ module.exports = {
new CopyPlugin([
{from: 'src/icons/svg/'}
]),
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
}),
]
}

View File

@ -11,11 +11,9 @@
"buildPlugin": "node build/build-async-plugins.js"
},
"dependencies": {
"@antv/g2plot": "^2.4.31",
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.18.9",
"@riophae/vue-treeselect": "0.4.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"vue": "2.6.10",
"vue-i18n": "7.3.2",
@ -33,6 +31,7 @@
"autoprefixer": "^7.1.2",
"babel-loader": "^8.0.6",
"chalk": "^2.0.1",
"compression-webpack-plugin": "^6.0.0",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^0.28.0",
"element-ui": "2.15.7",

View File

@ -32,7 +32,6 @@
</template>
<script>
import {Mix} from '@antv/g2plot'
import {uuid, hexColorToRGBA, setGradientColor} from '../../../utils/chartmix'
import ViewTrackBar from '../../../components/views/ViewTrackBar'
import {getRemark} from "../../../components/views/utils";
@ -44,7 +43,6 @@ import {
} from '../../../utils/map';
import ChartTitleUpdate from '../../../components/views/ChartTitleUpdate';
import {map, filter, join, flatten, cloneDeep} from 'lodash-es';
import {clear} from 'size-sensor'
import {valueFormatter} from '../../../utils/formatter'
export default {
@ -176,7 +174,7 @@ export default {
}
},
created() {
!this.$chartmix && (this.$chartmix = Mix)
!this.$chartmix && (this.$chartmix = this.$Mix)
},
mounted() {
this.preDraw()
@ -1153,7 +1151,7 @@ export default {
beforeDestroy() {
if (this.myChart.container) {
if (typeof this.myChart.container.getAttribute === 'function') {
clear(this.myChart.container)
this.$G2SizeSensorClear(this.myChart.container)
}
}
if (this.myChart) {

View File

@ -12,6 +12,8 @@ public class SymbolMapResultDTO extends AxisChartDataAntVDTO {
private String latitude;
private String color;
private Object busiValue;
private Map<String, Object> properties;

View File

@ -35,11 +35,15 @@ public class SymbolMapRSHandler implements PluginViewRSHandler<Map> {
public Map format(PluginViewParam pluginViewParam, List<String[]> data, boolean isDrill) {
List<PluginViewField> xAxis = new ArrayList<>();
List<PluginViewField> yAxis = new ArrayList<>();
List<PluginViewField> xAxisExt = new ArrayList<>();
pluginViewParam.getPluginViewFields().forEach(pluginViewField -> {
if (StringUtils.equals(pluginViewField.getTypeField(), "xAxis")) {
xAxis.add(pluginViewField);
}
if (StringUtils.equals(pluginViewField.getTypeField(), "xAxisExt")) {
xAxisExt.add(pluginViewField);
}
if (StringUtils.equals(pluginViewField.getTypeField(), "yAxis")
|| trans2Ykeys.contains(pluginViewField.getTypeField())) {
yAxis.add(pluginViewField);
@ -65,40 +69,31 @@ public class SymbolMapRSHandler implements PluginViewRSHandler<Map> {
}
if (CollectionUtils.isEmpty(yAxis)) {
for (int i = 0; i < xAxis.size() + yAxis.size(); i++) {
SymbolMapResultDTO axisChartDataDTO = new SymbolMapResultDTO();
axisChartDataDTO.setField(a.toString());
axisChartDataDTO.setName(a.toString());
SymbolMapResultDTO axisChartDataDTO = new SymbolMapResultDTO();
axisChartDataDTO.setField(a.toString());
axisChartDataDTO.setName(a.toString());
List<ChartDimensionDTO> dimensionList = new ArrayList<>();
List<ChartQuotaDTO> quotaList = new ArrayList<>();
List<ChartDimensionDTO> dimensionList = new ArrayList<>();
for (int j = 0; j < xAxis.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxis.get(j).getId());
chartDimensionDTO.setValue(row[j]);
dimensionList.add(chartDimensionDTO);
}
axisChartDataDTO.setDimensionList(dimensionList);
int j = i - xAxis.size();
if (j > -1) {
ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO();
chartQuotaDTO.setId(yAxis.get(j).getId());
quotaList.add(chartQuotaDTO);
axisChartDataDTO.setQuotaList(quotaList);
try {
axisChartDataDTO.setBusiValue(row[i]);
axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i]));
} catch (Exception e) {
axisChartDataDTO.setValue(new BigDecimal(0));
}
axisChartDataDTO.setCategory(yAxis.get(j).getName());
}
axisChartDataDTO.setLongitude(dimensionList.get(0).getValue());
axisChartDataDTO.setLatitude(dimensionList.get(1).getValue());
datalist.add(axisChartDataDTO);
for (int j = 0; j < xAxis.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxis.get(j).getId());
chartDimensionDTO.setValue(row[j]);
dimensionList.add(chartDimensionDTO);
}
for (int j = 0; j < xAxisExt.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxisExt.get(j).getId());
chartDimensionDTO.setValue(row[j + xAxis.size()]);
dimensionList.add(chartDimensionDTO);
}
axisChartDataDTO.setDimensionList(dimensionList);
axisChartDataDTO.setLongitude(dimensionList.get(0).getValue());
axisChartDataDTO.setLatitude(dimensionList.get(1).getValue());
if (!xAxisExt.isEmpty()) {
axisChartDataDTO.setColor(dimensionList.get(2).getValue());
}
datalist.add(axisChartDataDTO);
} else {
SymbolMapResultDTO axisChartDataDTO = new SymbolMapResultDTO();
axisChartDataDTO.setField(a.toString());
@ -112,10 +107,19 @@ public class SymbolMapRSHandler implements PluginViewRSHandler<Map> {
chartDimensionDTO.setValue(row[j]);
dimensionList.add(chartDimensionDTO);
}
for (int j = 0; j < xAxisExt.size(); j++) {
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
chartDimensionDTO.setId(xAxisExt.get(j).getId());
chartDimensionDTO.setValue(row[j + xAxis.size()]);
dimensionList.add(chartDimensionDTO);
}
if (!xAxisExt.isEmpty()) {
axisChartDataDTO.setColor(dimensionList.get(2).getValue());
}
axisChartDataDTO.setDimensionList(dimensionList);
axisChartDataDTO.setQuotaList(new ArrayList<>());
axisChartDataDTO.setProperties(new HashMap<>());
int step = xAxis.size();
int step = xAxis.size() + xAxisExt.size();
Boolean valueFilled = false;
for (int i = 0; i < yAxis.size(); i++) {
PluginViewField curY = yAxis.get(i);

View File

@ -140,7 +140,10 @@ public class SymbolMapService extends ViewPluginService {
if (CollectionUtils.isEmpty(xAxis) || xAxis.size() < 2) {
return null;
}
List<PluginViewField> xAxisExt = pluginViewParam.getFieldsByType("xAxisExt");
if (CollectionUtils.isNotEmpty(xAxisExt)) {
xAxisExt.forEach(i -> i.setTypeField("xAxis"));
}
if (CollectionUtils.isNotEmpty(yAxis)) {
String generateSQL = super.generateSQL(pluginViewParam);
pluginViewParam.setPluginViewFields(pluginViewFields);
@ -149,7 +152,7 @@ public class SymbolMapService extends ViewPluginService {
// 下面考虑符号大小为空的情况
String result = symbolMapStatHandler.build(pluginViewParam, this);
// pluginViewParam.setPluginViewFields(pluginViewFields);
pluginViewParam.setPluginViewFields(pluginViewFields);
return result;
}

View File

@ -1,6 +1,6 @@
<template>
<span>
<span style="position: relative;display: inline-block;">
<i class="el-icon-arrow-down el-icon-delete" style="position: absolute;top: 6px;right: 24px;color: #878d9f;cursor: pointer;z-index: 1;" @click="removeItem" />
<el-dropdown trigger="click" size="mini" @command="clickItem">
<span class="el-dropdown-link">
<el-tag size="small" class="item-axis" :type="tagType">
@ -20,24 +20,6 @@
<i class="el-icon-arrow-down el-icon--right" style="position: absolute;top: 6px;right: 10px;" />
</el-tag>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="sort">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<i class="el-icon-sort" />
<span>{{ $t('chart.sort') }}</span>
<span class="summary-span-item">({{ $t('chart.'+item.sort) }})</span>
</span>
<i class="el-icon-arrow-right el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="beforeSort('none')">{{ $t('chart.none') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSort('asc')">{{ $t('chart.asc') }}</el-dropdown-item>
<el-dropdown-item :command="beforeSort('desc')">{{ $t('chart.desc') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown-item>
<el-dropdown-item v-show="item.deType === 1" divided>
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="dateStyle">
<span class="el-dropdown-link inner-dropdown-menu">

View File

@ -18,6 +18,7 @@ export default {
dark: 'Dark',
label_format_tip: 'The field value can be read in the form of {field Name}, the fields in the label and the tips are interchangeable, and the built-in latitude and longitude related fields',
tooltip_format_tip: 'The field value can be read in the form of {field Name}, the fields in the label and the tips are interchangeable, and the built-in latitude and longitude related fields.(the label does not support line breaks)',
mark_size_tip: 'When this quota is in effect, the bubble size attribute in the style size will be invalid'
mark_size_tip: 'When this quota is in effect, the bubble size attribute in the style size will be invalid',
color: 'Color'
}
}

View File

@ -19,6 +19,7 @@ export default {
dark: '暗色',
label_format_tip: '可以${fieldName}的形式讀取字段值,標籤和提示中的字段互相通用,內置經緯度相關字段',
tooltip_format_tip: '可以${fieldName}的形式讀取字段值,標籤和提示中的字段互相通用,內置經緯度相關字段(標籤不支持換行)',
mark_size_tip: '該指標生效時,樣式大小中的氣泡大小屬性將失效'
mark_size_tip: '該指標生效時,樣式大小中的氣泡大小屬性將失效',
color: '顏色'
}
}

View File

@ -17,6 +17,7 @@ export default {
dark: '暗色',
label_format_tip: '可以${fieldName}的形式读取字段值,标签和提示中的字段互相通用,内置经纬度相关字段',
tooltip_format_tip: '可以${fieldName}的形式读取字段值,标签和提示中的字段互相通用,内置经纬度相关字段(标签不支持换行)',
mark_size_tip: '该指标生效时,样式大小中的气泡大小属性将失效'
mark_size_tip: '该指标生效时,样式大小中的气泡大小属性将失效',
color: '颜色'
}
}

View File

@ -66,7 +66,37 @@
<span class="drag-placeholder-style-span">{{ $t('chart.placeholder_field') }}</span>
</div>
</el-row>
<!--颜色-->
<el-row class="padding-lr" style="margin-top: 6px;">
<span style="width: 80px;text-align: right;">
<span>{{ $t('plugin_view_symbol_map.color') }}</span>/<span>{{ $t('chart.dimension') }}</span>
</span>
<draggable
v-model="colors"
:move="onMove"
animation="300"
class="drag-block-style" group="drag"
@add="addColor"
@update="calcData(true)"
>
<transition-group class="draggable-group">
<dimension-ext-item
v-for="(item,index) in colors"
:key="item.id" :chart="chart"
:dimension-data="dimensionData"
:index="index"
:item="item"
:param="param"
:quota-data="quotaData"
@onDimensionItemRemove="colorItemRemove"
@onNameEdit="showRename"
/>
</transition-group>
</draggable>
<div v-if="!colors || colors.length === 0" class="drag-placeholder-style">
<span class="drag-placeholder-style-span">{{ $t('chart.placeholder_field') }}</span>
</div>
</el-row>
<!-- 符号大小 -->
<el-row class="padding-lr" style="margin-top: 6px;">
<span style="width: 80px;text-align: right;">
@ -137,7 +167,7 @@
</el-row>
<FilterTree
ref="filterTree"
@filter-data="changeFilterData" @execute-axios="executeAxios"
@filter-data="changeFilterData" @execute-axios="executeAxios"
/>
</div>
@ -147,6 +177,7 @@
import LocationXItem from '@/components/views/LocationXItem'
import LocationYItem from '@/components/views/LocationYItem'
import QuotaItem from '@/components/views/QuotaItem'
import DimensionExtItem from '@/components/views/DimensionExtItem'
import FilterItem from '@/components/views/FilterItem'
import messages from '@/de-base/lang/messages'
import FilterTree from '@/components/views/filter/FilterTree.vue'
@ -170,7 +201,8 @@ export default {
LocationYItem,
QuotaItem,
FilterItem,
FilterTree
FilterTree,
DimensionExtItem
},
data() {
return {
@ -188,7 +220,8 @@ export default {
}
],
longitudes: [],
latitudes: []
latitudes: [],
colors: []
}
},
computed: {
@ -220,6 +253,7 @@ export default {
created() {
this.longitudes = this.view.xaxis && this.view.xaxis.length && [this.view.xaxis[0]] || []
this.latitudes = this.view.xaxis && this.view.xaxis.length > 1 && [this.view.xaxis[1]] || []
this.colors = this.view.xaxisExt && this.view.xaxisExt.length && [this.view.xaxisExt[0]] || []
this.$emit('on-add-languages', messages)
},
watch: {
@ -228,6 +262,9 @@ export default {
},
latitudes(val) {
this.view.xaxis = [...this.longitudes, ...this.latitudes]
},
colors(val) {
this.view.xaxisExt = this.colors
}
},
methods: {
@ -294,8 +331,22 @@ export default {
}
this.calcData(true)
},
addColor(e) {
this.multiAdd(e, this.colors)
this.dragMoveDuplicate(this.colors, e)
this.dragCheckType(this.colors, 'd')
if (this.colors.length > 1) {
this.colors = [this.colors[0]]
}
this.calcData(true)
},
colorItemRemove(item) {
this.colors.splice(item.index, 1)
this.calcData(true)
},
calcData(cache) {
this.view.xaxis = [...this.longitudes, ...this.latitudes]
this.view.xaxisExt = this.colors
this.$emit('plugin-call-back', {
eventName: 'calc-data',
eventParam: {

View File

@ -453,7 +453,12 @@ export default {
c.colors.forEach(ele => {
colors.push(hexColorToRGBA(ele, c.alpha))
})
this.pointLayer.color(colors[0])
const colorAxis = JSON.parse(chart.xaxisExt)
if (colorAxis && colorAxis.length) {
this.pointLayer.color('color', colors)
} else {
this.pointLayer.color(colors[0])
}
}
const yaxis = JSON.parse(chart.yaxis)
const hasYaxis = yaxis && yaxis.length

View File

@ -10,8 +10,12 @@ source ${DE_BASE}/dataease/.env
export COMPOSE_HTTP_TIMEOUT=180
compose_files="-f docker-compose.yml"
compose_cmd="docker-compose"
server_url=""
current_version=""
latest_version=""
owner=""
repo=""
docker-compose version >/dev/null 2>&1
if [ $? -ne 0 ]; then
@ -21,7 +25,6 @@ if [ $? -ne 0 ]; then
fi
fi
if [ "${DE_ENGINE_MODE}" = "local" ]; then
if [[ ! ${DE_EXTERNAL_KETTLE} ]] || [ ${DE_EXTERNAL_KETTLE} = "false" ]; then
compose_files="${compose_files} -f docker-compose-kettle.yml"
@ -84,6 +87,55 @@ function _healthcheck() {
echo "【警告】服务在等待时间内未完全启动!请稍后使用 dectl status 检查服务运行状况。"
echo
}
function _get_current_version() {
de_current_version=$(grep "^ image:.*/dataease:" ${DE_BASE}/dataease/docker-compose.yml | awk -F'dataease:' '{print $2}')
if test -z $de_current_version; then
echo "获取当前版本失败,请检查当前版本是否正确"
exit 1
fi
current_version=$de_current_version
}
function _get_available_server() {
git_urls=('gitee.com' 'github.com')
for git_url in ${git_urls[*]}
do
echo -ne "检测 ${git_url} ... "
curl -m 5 -kIs https://${git_url} >/dev/null
if [ $? != 0 ];then
echo "failed"
else
echo "ok"
server_url=${git_url}
break
fi
done
}
function _get_latest_version() {
if [[ -x "$(command -v python)" ]];then
py_cmd='python'
elif [[ -x "$(command -v python3)" ]]; then
py_cmd='python3'
fi
_get_available_server
if [[ "x${server_url}" == "x" ]];then
echo "无法连接版本服务器,请稍候重试"
exit 1
fi
if [[ "${server_url}" == "gitee.com" ]];then
owner='fit2cloud-feizhiyun'
repo='DataEase'
gitee_release_content=$(curl -s https://gitee.com/api/v5/repos/${owner}/${repo}/releases/latest)
# export LC_ALL="en_US.utf8"
latest_version=$($py_cmd -c "import json; obj=json.loads('$gitee_release_content', strict=False); print(obj['tag_name']);")
else
owner='dataease'
repo='dataease'
latest_version=$(curl -s https://api.github.com/repos/${owner}/${repo}/releases/latest | grep -e "\"tag_name\"" | sed -r 's/.*: "(.*)",/\1/')
fi
}
function status() {
echo
echo "DataEase 容器运行状态"
@ -143,8 +195,10 @@ function uninstall() {
}
function version() {
echo
de_version=$(grep "^ image:.*/dataease:" ${DE_BASE}/dataease/docker-compose.yml | awk -F'dataease:' '{print $2}')
echo $de_version
_get_current_version
echo "current version is $current_version"
_get_latest_version
echo "latest version is $latest_version"
}
function _clear_component_docker_images() {
component=$1
@ -193,55 +247,7 @@ function clear_logs() {
echo "清理完毕"
}
function upgrade() {
echo
git_urls=('gitee.com' 'github.com')
if [[ -x "$(command -v python)" ]];then
py_cmd='python'
elif [[ -x "$(command -v python3)" ]]; then
py_cmd='python3'
else
git_urls=('github.com')
fi
for git_url in ${git_urls[*]}
do
success="true"
for i in {1..3}
do
echo -ne "检测 ${git_url} ... ${i} "
curl -m 5 -kIs https://${git_url} >/dev/null
if [ $? != 0 ];then
echo "failed"
success="false"
break
else
echo "ok"
fi
done
if [[ ${success} == "true" ]];then
server_url=${git_url}
break
fi
done
if [[ "x${server_url}" == "x" ]];then
echo "没有找到稳定的下载服务器,请稍候重试"
exit 1
fi
if [[ "${server_url}" == "gitee.com" ]];then
owner='fit2cloud-feizhiyun'
repo='DataEase'
gitee_release_content=$(curl -s https://gitee.com/api/v5/repos/${owner}/${repo}/releases/latest)
# export LC_ALL="en_US.utf8"
latest_version=$($py_cmd -c "import json; obj=json.loads('$gitee_release_content', strict=False); print(obj['tag_name']);")
else
owner='dataease'
repo='dataease'
latest_version=$(curl -s https://api.github.com/repos/${owner}/${repo}/releases/latest | grep -e "\"tag_name\"" | sed -r 's/.*: "(.*)",/\1/')
fi
current_version=$(grep "^ image:.*/dataease:" ${DE_BASE}/dataease/docker-compose.yml | awk -F'dataease:' '{print $2}')
version
if [ "${latest_version}" = "" ];then
echo "未获取到最新版本"
@ -250,13 +256,19 @@ function upgrade() {
echo "最新版本与当前版本一致,退出升级过程"
exit 0
else
echo -e "\e[32m 检测到最新版本为\e[1;33m${latest_version}\e[0;32m 即将执行在线升级...\e[0m"
if [[ "$latest_version" =~ ^v2.* ]];then
echo "获取到的最新版本与当前版本不匹配,请访问 https://community.fit2cloud.com/#/products/dataease/downloads 下载离线安装包"
exit 1
else
echo -e "\e[32m 检测到最新版本为\e[1;33m${latest_version}\e[0;32m 即将执行在线升级...\e[0m"
fi
fi
sleep 2s
echo "使用下载服务器 ${server_url}"
cd /tmp
download_url="https://${server_url}/${owner}/${repo}/releases/download/${latest_version}/dataease-${latest_version}-online.tar.gz"
curl -LOk -m 60 -o dataease-${latest_version}-online.tar.gz $download_url
if [ $? -ne 0 ]; then
echo -e "\e[31m升级失败:连接下载服务器超时!\n可手动下载升级包然后执行\e[1;33m /bin/bash install.sh \e[0;31m离线升级也可以重新执行一次 dectl upgrade 命令。\e[0m"

View File

@ -9,7 +9,7 @@
<packaging>pom</packaging>
<properties>
<dataease.version>1.18.14</dataease.version>
<dataease.version>1.18.15</dataease.version>
</properties>
<name>dataease</name>

View File

@ -11,5 +11,7 @@ public class TableField {
private String fieldType;
private int fieldSize;
private int accuracy;
private boolean notNull;
private boolean primaryKey;
}