Merge branch 'dev' into pr@dev_export_data

This commit is contained in:
taojinlong 2024-04-07 15:30:43 +08:00
commit ab6d3d442b
85 changed files with 2012 additions and 869 deletions

View File

@ -1,5 +1,7 @@
package io.dataease.commons.utils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
@ -17,4 +19,16 @@ public class UrlTestUtils {
return false;
}
}
public static boolean isURLAvailable(String urlString) {
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
return responseCode == HttpURLConnection.HTTP_OK;
} catch (IOException e) {
return false;
}
}
}

View File

@ -109,6 +109,13 @@ public class ChartViewController {
return chartViewService.chartCopy(id, panelId);
}
@DePermission(type = DePermissionType.PANEL, level = ResourceAuthLevel.PANEL_LEVEL_MANAGE, paramIndex = 1)
@ApiOperation("复制")
@PostMapping("chartCopyWithId/{id}/{panelId}/{newId}")
public String chartCopyWithId(@PathVariable String id, @PathVariable String panelId, @PathVariable String newId) {
return chartViewService.chartCopy(id, newId,panelId);
}
@DePermission(type = DePermissionType.PANEL, level = ResourceAuthLevel.PANEL_LEVEL_MANAGE, paramIndex = 1)
@ApiOperation("批量复制")
@PostMapping("chartBatchCopy/{panelId}")

View File

@ -613,7 +613,7 @@
<delete id="deleteNoUseView">
delete from chart_view
where scene_id = #{panelId}
where scene_id = #{panelId} and create_time &lt; ( unix_timestamp()- 30 ) * 1000
<if test="viewIds != null and viewIds.size() > 0">
and id not in
<foreach collection="viewIds" item="viewId" open='(' separator=',' close=')'>

View File

@ -219,7 +219,7 @@
AND t3.`name` LIKE CONCAT('%',#{taskName},'%')
</if>
</where>
ORDER BY t1.end_time DESC, t1.start_time
ORDER BY t1.end_time, t1.start_time
</select>
<select id="listFinishedUserTask" resultMap="BaseResultMapUserTaskDTO">

View File

@ -199,7 +199,7 @@
and panel_group.level = #{level}
</if>
</where>
ORDER BY panel_group.node_type desc, CONVERT(panel_group.name using gbk)
ORDER BY panel_group.create_time desc
</select>
<delete id="deleteLinkDefaultCircle">

View File

@ -83,8 +83,10 @@ public class JdbcProvider extends DefaultJdbcProvider {
try (Connection connection = getConnectionFromPool(datasourceRequest); PreparedStatement stat = getPreparedStatement(connection, queryTimeout, datasourceRequest.getQuery())) {
if (CollectionUtils.isNotEmpty(datasourceRequest.getTableFieldWithValues())) {
LogUtil.info("execWithPreparedStatement sql: " + datasourceRequest.getQuery());
for (int i = 0; i < datasourceRequest.getTableFieldWithValues().size(); i++) {
stat.setObject(i + 1, datasourceRequest.getTableFieldWithValues().get(i).getValue(), datasourceRequest.getTableFieldWithValues().get(i).getType());
LogUtil.info("execWithPreparedStatement param[" + (i + 1) + "]: " + datasourceRequest.getTableFieldWithValues().get(i).getValue());
}
}
@ -101,8 +103,12 @@ public class JdbcProvider extends DefaultJdbcProvider {
@Override
public List<TableField> getTableFields(DatasourceRequest datasourceRequest) throws Exception {
String requestTableName = datasourceRequest.getTable();
if (datasourceRequest.isLowerCaseTaleNames()) {
requestTableName = requestTableName.toLowerCase();
}
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase("mongo")) {
datasourceRequest.setQuery("select * from " + datasourceRequest.getTable());
datasourceRequest.setQuery("select * from " + requestTableName);
return fetchResultField(datasourceRequest);
}
List<TableField> list = new LinkedList<>();
@ -115,7 +121,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
}
}
DatabaseMetaData databaseMetaData = connection.getMetaData();
String tableNamePattern = datasourceRequest.getTable();
String tableNamePattern = requestTableName;
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.mysql.name())) {
if (databaseMetaData.getDriverMajorVersion() < 8) {
tableNamePattern = String.format(MySQLConstants.KEYWORD_TABLE, tableNamePattern);
@ -144,22 +150,25 @@ public class JdbcProvider extends DefaultJdbcProvider {
} else {
database = primaryKeys.getString("TABLE_CAT");
}
if (datasourceRequest.isLowerCaseTaleNames()) {
tableName = tableName.toLowerCase();
}
//获取主键的名称
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
if (tableName.equals(requestTableName) && 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))) {
if (tableName.equals(requestTableName) && 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))) {
if (tableName.equals(requestTableName) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
if (tableName.equals(requestTableName)) {
primaryKeySet.add(primaryKeys.getString("COLUMN_NAME"));
}
}
@ -177,24 +186,27 @@ public class JdbcProvider extends DefaultJdbcProvider {
} else {
database = resultSet.getString("TABLE_CAT");
}
if (datasourceRequest.isLowerCaseTaleNames()) {
tableName = tableName.toLowerCase();
}
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
if (tableName.equals(requestTableName) && database.equalsIgnoreCase(getDsSchema(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))) {
if (tableName.equals(requestTableName) && database.equalsIgnoreCase(getDatabase(datasourceRequest)) && schema.equalsIgnoreCase(getDsSchema(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
} else {
if (database != null) {
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
if (tableName.equals(requestTableName) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
} else {
if (tableName.equals(datasourceRequest.getTable())) {
if (tableName.equals(requestTableName)) {
TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet);
list.add(tableField);
}
@ -207,7 +219,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
DataEaseException.throwException(e);
} catch (Exception e) {
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase("ds_doris") || datasourceRequest.getDatasource().getType().equalsIgnoreCase("StarRocks")) {
datasourceRequest.setQuery("select * from " + datasourceRequest.getTable());
datasourceRequest.setQuery("select * from " + requestTableName);
return fetchResultField(datasourceRequest);
} else {
DataEaseException.throwException(Translator.get("i18n_datasource_connect_error") + e.getMessage());
@ -426,10 +438,11 @@ public class JdbcProvider extends DefaultJdbcProvider {
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(dsr.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = jdbcConfiguration.getQueryTimeout() > 0 ? jdbcConfiguration.getQueryTimeout() : 0;
try (Connection connection = getConnectionFromPool(dsr); PreparedStatement stat = getPreparedStatement(connection, queryTimeout, dsr.getQuery())) {
LogUtil.info("getData sql: " + dsr.getQuery());
if (CollectionUtils.isNotEmpty(dsr.getTableFieldWithValues())) {
for (int i = 0; i < dsr.getTableFieldWithValues().size(); i++) {
stat.setObject(i + 1, dsr.getTableFieldWithValues().get(i).getValue(), dsr.getTableFieldWithValues().get(i).getType());
LogUtil.info("getData param[" + (i + 1) + "]: " + dsr.getTableFieldWithValues().get(i).getValue());
}
}

View File

@ -26,6 +26,11 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider {
private static final String dropTableSql = "DROP TABLE IF EXISTS `TABLE_NAME`";
@Override
public String getLowerCaseTaleNames() {
return "SHOW VARIABLES LIKE 'lower_case_table_names'";
}
@Override
public String dropTableSql(String table) {
return dropTableSql.replace("TABLE_NAME", table);
@ -262,7 +267,7 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider {
if (field.getAccuracy() != null && field.getAccuracy() >= 0) {
str.append(field.getAccuracy());
} else {
str.append(4);
str.append(8);
}
str.append(") ");
break;
@ -288,9 +293,9 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider {
}
if (primaryKeyField != null) {
str.append("constraint ")
str.append("constraint `")
.append(table)
.append("_pk ")
.append("_pk` ")
.append("PRIMARY KEY (")
.append("`")
.append(primaryKeyField.getColumnName())

View File

@ -1,5 +1,6 @@
package io.dataease.service.ai;
import io.dataease.commons.utils.UrlTestUtils;
import io.dataease.service.system.SystemParameterService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@ -23,7 +24,7 @@ public class AiBaseService {
String baseUrl = parameterService.getValue("ai.baseUrl");
Map<String,String> result = new HashMap<>();
if(StringUtils.isNotEmpty(baseUrl)){
if(StringUtils.isNotEmpty(baseUrl) && UrlTestUtils.isURLAvailable(baseUrl)){
result.put("ai.baseUrl",baseUrl);
}

View File

@ -1076,7 +1076,9 @@ public class ChartViewService {
xAxis.addAll(xAxisExtList);
}
fieldMap.put("xAxis", xAxis);
fieldMap.put("xAxisExt", xAxisExt);
if (!StringUtils.equals(view.getType(), "race-bar")) {
fieldMap.put("xAxisExt", xAxisExt);
}
fieldMap.put("extStack", extStack);
fieldMap.put("extBubble", extBubble);
fieldMap.put("yAxis", yAxis);
@ -1515,7 +1517,11 @@ public class ChartViewService {
preDataItems.forEach(preDataItem -> {
String[] groupStackAxisArr = Arrays.copyOfRange(preDataItem, finalXAxisBase.size(), finalSubEndIndex);
String groupStackAxis = StringUtils.join(groupStackAxisArr, '-');
preDataMap.put(groupStackAxis, new BigDecimal(preDataItem[finalDataIndex]));
String preVal = preDataItem[finalDataIndex];
if (StringUtils.isBlank(preVal)) {
preVal = "0";
}
preDataMap.put(groupStackAxis, new BigDecimal(preVal));
});
curDataItems.forEach(curDataItem -> {
String[] groupStackAxisArr = Arrays.copyOfRange(curDataItem, finalXAxisBase.size(), finalSubEndIndex);
@ -1532,10 +1538,14 @@ public class ChartViewService {
final int index = dataIndex;
final AtomicReference<BigDecimal> accumValue = new AtomicReference<>(new BigDecimal(0));
data.forEach(item -> {
BigDecimal curVal = new BigDecimal(item[index]);
BigDecimal curAccumValue = accumValue.get().add(curVal);
String val = item[index];
BigDecimal curAccumValue = accumValue.get();
if (!StringUtils.isBlank(val)) {
BigDecimal curVal = new BigDecimal(val);
curAccumValue = curAccumValue.add(curVal);
accumValue.set(curAccumValue);
}
item[index] = curAccumValue.toString();
accumValue.set(curAccumValue);
});
}
}
@ -2191,7 +2201,13 @@ public class ChartViewService {
List<SqlVariableDetails> sqlVariables = gson.fromJson(table.getSqlVariableDetails(), new TypeToken<List<SqlVariableDetails>>() {
}.getType());
if (requestList != null && CollectionUtils.isNotEmpty(requestList.getFilter())) {
for (ChartExtFilterRequest chartExtFilterRequest : requestList.getFilter()) {
if (CollectionUtils.isNotEmpty(chartExtFilterRequest.getValue())) {
List<String> collect = chartExtFilterRequest.getValue().stream().map(SQLUtils::transKeyword).collect(Collectors.toList());
chartExtFilterRequest.setValue(collect);
}
if (CollectionUtils.isEmpty(chartExtFilterRequest.getValue())) {
continue;
}

View File

@ -11,6 +11,7 @@ import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.plugins.common.base.domain.DataFillFormWithBLOBs;
import io.dataease.plugins.common.base.domain.Datasource;
import io.dataease.plugins.common.base.mapper.DataFillFormMapper;
import io.dataease.plugins.common.constants.DatasourceTypes;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.exception.DataEaseException;
@ -59,6 +60,21 @@ public class DataFillDataService {
private final static Gson gson = new Gson();
public static void setLowerCaseRequest(Datasource ds, Provider datasourceProvider, ExtDDLProvider extDDLProvider, DatasourceRequest datasourceRequest) throws Exception {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(ds.getType());
switch (datasourceType) {
case mysql:
case mariadb:
String checkLowerCaseSql = extDDLProvider.getLowerCaseTaleNames();
datasourceRequest.setQuery(checkLowerCaseSql);
List<String[]> checkLowerCaseData = datasourceProvider.getData(datasourceRequest);
long lowCase = NumberUtils.toLong(checkLowerCaseData.get(0)[1]);
datasourceRequest.setLowerCaseTaleNames(lowCase > 0);
break;
default:
datasourceRequest.setLowerCaseTaleNames(true);
}
}
public DataFillFormTableDataResponse listData(DataFillFormTableDataRequest searchRequest) throws Exception {
@ -76,6 +92,11 @@ public class DataFillDataService {
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
setLowerCaseRequest(ds, datasourceProvider, extDDLProvider, datasourceRequest);
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
Map<String, ExtTableField.BaseType> extTableFieldTypeMap = new HashMap<>();
Map<String, TableField> tableFieldMap = new HashMap<>();
@ -125,7 +146,6 @@ public class DataFillDataService {
}
}
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
String whereSql = "";
if (StringUtils.isNoneBlank(searchRequest.getPrimaryKeyValue())) {
@ -232,6 +252,9 @@ public class DataFillDataService {
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
setLowerCaseRequest(ds, datasourceProvider, extDDLProvider, datasourceRequest);
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest).stream().filter(TableField::isPrimaryKey).collect(Collectors.toList());
if (CollectionUtils.isEmpty(tableFields)) {
throw new RuntimeException("没有主键");
@ -274,10 +297,14 @@ public class DataFillDataService {
Datasource ds = datasource.get(dataFillForm.getDatasource());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
setLowerCaseRequest(ds, datasourceProvider, extDDLProvider, datasourceRequest);
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
Map<String, TableField> tableFieldMap = new HashMap<>();
@ -306,18 +333,18 @@ public class DataFillDataService {
if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) {
String name1 = field.getSettings().getMapping().getColumnName1();
String name2 = field.getSettings().getMapping().getColumnName2();
if (tableFieldMap.containsKey(name1) && data.containsKey(name1) && data.get(name1) != null) {
if (tableFieldMap.containsKey(name1)) {
DatasourceRequest.TableFieldWithValue value1 = new DatasourceRequest.TableFieldWithValue()
.setValue(new java.sql.Date((long) data.get(name1)))
.setValue(data.get(name1) != null ? new java.sql.Date((long) data.get(name1)) : null)
.setFiledName(name1)
.setTypeName(tableFieldMap.get(name1).getFieldType())
.setType(tableFieldMap.get(name1).getType());
searchFields.add(value1);
extTableFields.put(name1, field);
}
if (tableFieldMap.containsKey(name2) && data.containsKey(name2) && data.get(name2) != null) {
if (tableFieldMap.containsKey(name2)) {
DatasourceRequest.TableFieldWithValue value2 = new DatasourceRequest.TableFieldWithValue()
.setValue(new java.sql.Date((long) data.get(name2)))
.setValue(data.get(name2) != null ? new java.sql.Date((long) data.get(name2)) : null)
.setFiledName(name2)
.setTypeName(tableFieldMap.get(name2).getFieldType())
.setType(tableFieldMap.get(name2).getType());
@ -326,7 +353,7 @@ public class DataFillDataService {
}
} else {
String name = field.getSettings().getMapping().getColumnName();
if (tableFieldMap.containsKey(name) && data.containsKey(name) && data.get(name) != null) {
if (tableFieldMap.containsKey(name)) {
DatasourceRequest.TableFieldWithValue value = new DatasourceRequest.TableFieldWithValue()
.setValue(data.get(name))
.setFiledName(name)
@ -334,14 +361,14 @@ public class DataFillDataService {
.setType(tableFieldMap.get(name).getType());
if (StringUtils.equalsIgnoreCase(field.getType(), "date")) {
value.setValue(new java.sql.Date((long) data.get(name)));
value.setValue(data.get(name) != null ? new java.sql.Date((long) data.get(name)) : null);
}
searchFields.add(value);
extTableFields.put(name, field);
// 关于unique的字段判断
if (field.getSettings().isUnique()) {
if (field.getSettings().isUnique() && data.get(name) != null) {
uniqueFields.add(value);
}
@ -349,8 +376,6 @@ public class DataFillDataService {
}
}
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
if (CollectionUtils.isNotEmpty(uniqueFields)) {
for (DatasourceRequest.TableFieldWithValue uniqueField : uniqueFields) {

View File

@ -4,7 +4,10 @@ import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.dataease.auth.annotation.DeCleaner;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.constants.*;
import io.dataease.commons.constants.DataFillConstants;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.commons.constants.SysAuthConstants;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.utils.*;
import io.dataease.controller.ResultHolder;
import io.dataease.controller.request.datafill.DataFillFormRequest;
@ -12,7 +15,6 @@ import io.dataease.dto.DatasourceDTO;
import io.dataease.dto.datafill.DataFillFormDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.i18n.Translator;
import io.dataease.listener.util.CacheUtils;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.DataFillFormMapper;
import io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper;
@ -158,6 +160,10 @@ public class DataFillService {
Assert.notNull(dataFillForm.getId(), "id cannot be null");
DataFillFormWithBLOBs form = dataFillFormMapper.selectByPrimaryKey(dataFillForm.getId());
//todo 改变文件夹位置
checkName(dataFillForm.getId(), dataFillForm.getName(), form.getPid(), form.getLevel(), form.getNodeType(), DataFillConstants.OPT_TYPE_UPDATE);
dataFillForm.setUpdateTime(new Date());
dataFillFormMapper.updateByPrimaryKeySelective(dataFillForm);
@ -262,9 +268,13 @@ public class DataFillService {
dataFillFormMapper.deleteByExample(example);
}
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.DELETE, SysLogConstants.SOURCE_TYPE.DATA_FILL_FORM, dataFillForm.getId(), dataFillForm.getPid(), null, null);
if (dataFillForm != null) {
dataFillTaskService.deleteTaskByFormId(id);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.DELETE, SysLogConstants.SOURCE_TYPE.DATA_FILL_FORM, dataFillForm.getId(), dataFillForm.getPid(), null, null);
dataFillTaskService.deleteTaskByFormId(id);
}
}
public List<ExtTableField> listFields(String id) throws Exception {
@ -309,10 +319,14 @@ public class DataFillService {
Datasource ds = datasource.get(dataFillForm.getDatasource());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
DataFillDataService.setLowerCaseRequest(ds, datasourceProvider, extDDLProvider, datasourceRequest);
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
for (TableField tableField : tableFields) {

View File

@ -9,6 +9,7 @@ import io.dataease.controller.request.datafill.DataFillUserTaskSearchRequest;
import io.dataease.dto.datafill.DataFillTaskDTO;
import io.dataease.dto.datafill.DataFillUserTaskDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.i18n.Translator;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.job.sechedule.strategy.TaskHandler;
import io.dataease.job.sechedule.strategy.TaskStrategyFactory;
@ -94,12 +95,33 @@ public class DataFillTaskService {
if (request.getId() == null) {
insert = true;
request.setFormId(formId);
request.setCreateTime(new Date());
}
if (insert) {
dataFillTaskMapper.insertSelective(request);
if (StringUtils.isNotBlank(request.getName())) {
DataFillTaskExample example = new DataFillTaskExample();
DataFillTaskExample.Criteria criteria = example.createCriteria()
.andFormIdEqualTo(formId)
.andNameEqualTo(request.getName());
if (insert) {
if (dataFillTaskMapper.countByExample(example) > 0) {
DataEaseException.throwException(Translator.get("I18N_DATA_FILL_TASK_EXIST"));
}
dataFillTaskMapper.insertSelective(request);
} else {
criteria.andIdNotEqualTo(request.getId());
if (dataFillTaskMapper.countByExample(example) > 0) {
DataEaseException.throwException(Translator.get("I18N_DATA_FILL_TASK_EXIST"));
}
dataFillTaskMapper.updateByPrimaryKeySelective(request);
}
} else {
dataFillTaskMapper.updateByPrimaryKeySelective(request);
if (insert) {
dataFillTaskMapper.insertSelective(request);
} else {
dataFillTaskMapper.updateByPrimaryKeySelective(request);
}
}
DataFillTaskWithBLOBs task = dataFillTaskMapper.selectByPrimaryKey(request.getId());
@ -197,7 +219,8 @@ public class DataFillTaskService {
Date endTime = null;
if (dataFillTask.getRateType() == -1) {
startTime = dataFillTask.getPublishStartTime();
//startTime = dataFillTask.getPublishStartTime();
startTime = new Date();
endTime = dataFillTask.getPublishEndTime();
} else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

View File

@ -1022,6 +1022,7 @@ public class ExtractDataService {
case pg:
PgConfiguration pgConfiguration = new Gson().fromJson(datasource.getConfiguration(), PgConfiguration.class);
dataMeta = new DatabaseMeta("db", "POSTGRESQL", "Native", pgConfiguration.getHost().trim(), pgConfiguration.getDataBase(), pgConfiguration.getPort().toString(), pgConfiguration.getUsername(), pgConfiguration.getPassword());
dataMeta.setPreferredSchemaName(pgConfiguration.getSchema());
transMeta.addDatabase(dataMeta);
inputSteps = inputStep(transMeta, selectSQL, pgConfiguration);
udjcStep = udjc(datasetTableFields, DatasourceTypes.pg, pgConfiguration, isSetKey);

View File

@ -395,6 +395,10 @@ public class PanelLinkService {
return ticketDto;
}
Long exp = linkTicket.getExp();
if (ObjectUtils.isEmpty(exp) || exp.equals(0L)) {
ticketDto.setTicketExp(false);
return ticketDto;
}
long expTime = exp * 60L * 1000L;
long time = now - accessTime;
ticketDto.setTicketExp(time > expTime);

View File

@ -131,8 +131,12 @@ public class PanelViewService {
//将视图从cache表中更新到正式表中
viewIds = panelViewInsertDTOList.stream().map(panelView -> panelView.getChartViewId()).collect(Collectors.toList());
}
extChartViewMapper.deleteCacheWithPanel(viewIds, panelId);
extChartViewMapper.deleteNoUseView(viewIds, panelId);
// viewIds 不存在时 不执行删除缓存防止误删情况
if(CollectionUtils.isNotEmpty(viewIds)){
extChartViewMapper.deleteCacheWithPanel(viewIds, panelId);
extChartViewMapper.deleteNoUseView(viewIds, panelId);
}
}
panelGroup.setMobileLayout(mobileLayout);
return viewIds;

View File

@ -221,6 +221,40 @@
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--数据填报缓存-->
<cache
name="user_data_fill"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<cache
name="role_data_fill"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<cache
name="dept_data_fill"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--组织授权数据源缓存-->
<cache

View File

@ -239,6 +239,7 @@ I18N_DS_INVALID_TABLE=Datasource has invalid tables
I18N_ACCOUNT_LOCKED=Account\u3010%s\u3011is locked(Please contact the administrator to unlock or try again in %s minutes)
I18N_PANEL_EXIST=The current panel name already exists under this directory
I18N_DATA_FILL_FORM_EXIST=The current data filling form name already exists under this directory
I18N_DATA_FILL_TASK_EXIST=The current data filling task name already exists under this form
I18N_FOlDER_EXIST=The name already exists under this directory
I18N_DATASET_GROUP_EXIST=The current dataset grouping name already exists under this directory
I18N_NOT_JAR=File is not jar!

View File

@ -239,6 +239,7 @@ I18N_DS_INVALID_TABLE=\u6570\u636E\u6E90\u4E2D\u6709\u65E0\u6548\u7684\u8868
I18N_ACCOUNT_LOCKED=\u8D26\u53F7\u3010%s\u3011\u5DF2\u9501\u5B9A(\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u89E3\u9501\u6216%s\u5206\u949F\u540E\u91CD\u8BD5)
I18N_PANEL_EXIST=\u5F53\u524D\u4EEA\u8868\u677F\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_DATA_FILL_FORM_EXIST=\u5F53\u524D\u6570\u636E\u586B\u62A5\u8868\u5355\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_DATA_FILL_TASK_EXIST=\u5F53\u524D\u6570\u636E\u586B\u62A5\u4EFB\u52A1\u540D\u79F0\u5728\u8BE5\u8868\u5355\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_FOlDER_EXIST=\u5F53\u524D\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_DATASET_GROUP_EXIST=\u5F53\u524D\u6570\u636E\u96C6\u5206\u7EC4\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_NOT_JAR=\u6587\u4EF6\u4E0D\u662F jar \u5305!

View File

@ -235,6 +235,7 @@ I18N_DS_INVALID_TABLE=\u6578\u64DA\u6E90\u4E2D\u6709\u7121\u6548\u7684\u8868
I18N_ACCOUNT_LOCKED=\u8CEC\u865F\u3010%s\u3011\u5DF2\u9396\u5B9A(\u8ACB\u806F\u7CFB\u7BA1\u7406\u54E1\u89E3\u9396\u6216%s\u5206\u9418\u5F8C\u91CD\u8A66)
I18N_PANEL_EXIST=\u7576\u524D\u5100\u9336\u95C6\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_DATA_FILL_FORM_EXIST=\u7576\u524D\u6578\u64DA\u586B\u5831\u8868\u55AE\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_DATA_FILL_TASK_EXIST=\u7576\u524D\u6578\u64DA\u586B\u5831\u4EFB\u52D9\u540D\u7A31\u5728\u8A72\u8868\u55AE\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_FOlDER_EXIST=\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_DATASET_GROUP_EXIST=\u7576\u524D\u6578\u64DA\u96C6\u5206\u7D44\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_NOT_JAR=\u6587\u4EF6\u4E0D\u662F jar \u5305!

View File

@ -260,7 +260,7 @@ export default {
showPosition: {
type: String,
required: false,
default: 'NotProvided'
default: 'preview'
},
panelInfo: {
type: Object,
@ -828,26 +828,21 @@ export default {
if (this.componentData) {
const componentData = deepCopy(this.componentData)
componentData.forEach(component => {
if (!this.isMainCanvas() && component.type === 'custom' && component.options?.attrs?.selectFirst && this.format(component.style.width, this.scaleWidth) < 80) {
// do continue
} else {
Object.keys(component.style).forEach(key => {
if (this.needToChangeHeight.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleHeight)
Object.keys(component.style).forEach(key => {
if (this.needToChangeHeight.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleHeight)
}
if (this.needToChangeWidth.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleWidth)
}
if (this.needToChangeInnerWidth.includes(key)) {
if ((key === 'fontSize' || key === 'activeFontSize') && (this.terminal === 'mobile' || ['custom'].includes(component.type))) {
// do nothing ( v-text )
} else {
component.style[key] = this.formatPoint(component.style[key], this.previewCanvasScale.scalePointWidth)
}
if (this.needToChangeWidth.includes(key)) {
component.style[key] = this.format(component.style[key], this.scaleWidth)
}
if (this.needToChangeInnerWidth.includes(key)) {
if ((key === 'fontSize' || key === 'activeFontSize') && (this.terminal === 'mobile' || ['custom'].includes(component.type))) {
// do nothing ( v-text )
} else {
component.style[key] = this.formatPoint(component.style[key], this.previewCanvasScale.scalePointWidth)
}
}
})
}
}
})
const maxWidth = this.canvasStyleData.width * this.scaleWidth / 100
if (component.style['width'] > maxWidth) {
component.style['width'] = maxWidth

View File

@ -10,7 +10,7 @@
:src="element.frameLinks.src"
scrolling="auto"
frameborder="0"
class="main-frame"
class="main-frame main-de-iframe "
@load="loaded"
@error="onError"
/>
@ -103,6 +103,14 @@ export default {
mounted() {
bus.$on('frameLinksChange-' + this.element.id, this.frameLinksChange)
eventBus.$on('startMoveIn', this.frameLinksChange)
window.addEventListener('click', function(event) {
const iframes = document.getElementsByClassName('main-de-iframe')
if (iframes) {
iframes.forEach(function(iframe) {
iframe.contentWindow.postMessage('closeFilterComponent', '*')
})
}
})
},
beforeDestroy() {
bus.$off('frameLinksChange-' + this.element.id, this.frameLinksChange)

View File

@ -1,6 +1,7 @@
<template>
<div
v-loading="loadingFlag"
element-loading-background="rgba(0,0,0,0)"
:class="[
{
['active']: active

View File

@ -124,7 +124,8 @@ export const customAttrTrans = {
'quotaSuffixFontSize'
],
'label': [
'fontSize'
'fontSize',
'subFontSize'
],
'tooltip': {
'textStyle': ['fontSize']

View File

@ -180,10 +180,12 @@ export function panelDataPrepare(componentData, componentStyle, callback) {
})
// 初始化密度为最高密度
componentStyle.aidedDesign.matrixBase = 4
callback({
const result = {
'componentData': resetID(componentData),
'componentStyle': componentStyle
})
}
store.state.sourceComponentData = deepCopy(result.componentData)
callback(result)
}
export function resetID(data) {
@ -308,6 +310,8 @@ export function imgUrlTrans(url) {
export function getNowCanvasComponentData(canvasId, showPosition) {
if (showPosition && (showPosition.includes('email-task') || showPosition.includes('multiplexing'))) {
return store.state.previewComponentData.filter(item => item.canvasId === canvasId)
} else if (showPosition === 'preview') {
return deepCopy(store.state.sourceComponentData.filter(item => item.canvasId === canvasId))
} else {
return store.state.componentData.filter(item => item.canvasId === canvasId)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,26 @@
<template>
<el-radio-group @change="visualChange" v-model="selectValue">
<el-radio-group
style="height: 40px; line-height: 40px"
@change="visualChange"
v-model="selectValue"
>
<template v-for="item in options">
<el-radio
:key="item.id + 'radio'"
:label="item.text"
:value="item.id"
:label="item.id"
class="is-custom-select"
v-if="radioStyle.showStyle === 'single'"
:disabled="itemDisabled"
/>
>{{ item.text }}</el-radio
>
<el-radio-button
v-else
:disabled="itemDisabled"
:key="item.id + 'tab'"
:label="item.text"
:value="item.id"
/>
class="is-custom-select"
:label="item.id"
>{{ item.text }}</el-radio-button
>
</template>
</el-radio-group>
</template>
@ -91,7 +97,7 @@ export default {
},
radioStyle: {
handler() {
this.setPlaceholderColor()
this.setPlaceholderColor();
},
deep: true,
},
@ -104,20 +110,20 @@ export default {
});
},
beforeDestroy() {
let styleEle = document.querySelector(`#radio-style${this.id}`)
let styleEle = document.querySelector(`#radio-style${this.id}`);
if (styleEle) {
styleEle. parentElement.removeChild(styleEle)
styleEle.parentElement.removeChild(styleEle);
}
},
methods: {
setPlaceholderColor() {
let styleEle = document.querySelector(`#radio-style${this.id}`)
let styleEle = document.querySelector(`#radio-style${this.id}`);
if (!styleEle) {
styleEle = document.createElement('style')
styleEle.id = `radio-style${this.id}`
document.querySelector('head').appendChild(styleEle)
styleEle = document.createElement("style");
styleEle.id = `radio-style${this.id}`;
document.querySelector("head").appendChild(styleEle);
}
styleEle.innerHTML = `#component${this.id} {\n color: transparent !important; \n border-color:transparent !important; \n background-color: transparent !important; \n } #component${this.id} .el-radio-button:not(.is-active) .el-radio-button__inner {\n color: ${this.radioStyle.wordColor}; \n border-color: ${this.radioStyle.brColor}; \n background-color: ${this.radioStyle.innerBgColor}; \n } #component${this.id} .el-radio:not(.is-check) .el-radio__label {\n color: ${this.radioStyle.wordColor}; \n }`
styleEle.innerHTML = `#component${this.id} .el-radio-button:not(.is-active) .el-radio-button__inner {\n color: ${this.radioStyle.wordColor}; \n border-color: ${this.radioStyle.brColor}; \n background-color: ${this.radioStyle.innerBgColor}; \n } #component${this.id} .el-radio:not(.is-check) .el-radio__label {\n color: ${this.radioStyle.wordColor}; \n }`;
},
resetList(arrays) {
if (Array.isArray(arrays)) {

View File

@ -108,7 +108,7 @@ export default {
computed: {
mode() {
let result = 'el-select'
if (this.element.style.showMode && this.element.style.showMode === 'radio' && !this.element.options.attrs.multiple && !this.isConfig) {
if (this.element.style.showMode && this.element.style.showMode === 'radio' && !this.element.options.attrs.multiple && !this.isConfig && this.element.options.attrs.required) {
return 'DeRadio'
}
if (this.element.options && this.element.options.attrs && this.element.options.attrs.visual) {

View File

@ -84,6 +84,7 @@
:panel-info="panelInfo"
:in-screen="inScreen"
:show-position="showPosition"
:user-id="userId"
/>
</div>
@ -280,6 +281,10 @@ export default {
terminal: {
type: String,
default: 'pc'
},
userId: {
type: String,
require: false
}
},
data() {

View File

@ -67,7 +67,6 @@ export default {
},
methods: {
handlerInputStyle(type, newValue) {
if (this.element.style.showMode && this.element.style.showMode === 'radio') return
let nodeCache = ''
this.styleAttrs.forEach(ele => {
if (!nodeCache) {

View File

@ -20,7 +20,7 @@ function checkPermission(el, binding) {
}
export function hasPermission(binding) {
const { value } = binding
const value = binding
// 我们是基于资源授鉴权 不用角色 因为后期可能有对部门授权 对 人员授权
const permissions = store.getters && store.getters.permissions
if (value && value instanceof Array) {
@ -30,7 +30,6 @@ export function hasPermission(binding) {
const result = permissions.includes(needP)
return result
})
console.log(needPermissions, hasPermission)
return hasPermission
} else {
return false

View File

@ -0,0 +1 @@
<svg style="vertical-align: middle;overflow: hidden;" t="1710214539671" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16"><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM601.6 401.066667c4.266667 8.533333 12.8 17.066667 21.333333 21.333333 4.266667 4.266667 12.8 4.266667 17.066667 4.266667h256c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667h-153.6l226.133333-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733333-8.533333-8.533333-17.066667-12.8-29.866666-12.8s-21.333333 4.266667-29.866667 12.8L682.666667 281.6V128c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667v256c0 4.266667 0 12.8 4.266667 17.066667zM115.2 968.533333L341.333333 742.4V896c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666667-42.666667v-256c0-4.266667 0-12.8-4.266667-17.066667-4.266667-8.533333-12.8-17.066667-21.333333-21.333333-4.266667-4.266667-12.8-4.266667-17.066667-4.266667H128c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h153.6l-226.133333 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733333s42.666667 17.066667 59.733333 0z" p-id="10189"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg t="1710150885892" style="vertical-align: middle;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="rgb(100, 106, 115)" width="16" height="16"><path d="M85.333333 384c25.6 0 42.666667-17.066667 42.666667-42.666667V128h213.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666666H85.333333c-25.6 0-42.666667 17.066667-42.666666 42.666666v256c0 25.6 17.066667 42.666667 42.666666 42.666667zM938.666667 640c-25.6 0-42.666667 17.066667-42.666667 42.666667v213.333333h-213.333333c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666666h256c25.6 0 42.666667-17.066667 42.666666-42.666666v-256c0-25.6-17.066667-42.666667-42.666666-42.666667zM977.066667 68.266667c-4.266667-8.533333-12.8-17.066667-21.333334-21.333334-4.266667-4.266667-12.8-4.266667-17.066666-4.266666h-256c-25.6 0-42.666667 17.066667-42.666667 42.666666s17.066667 42.666667 42.666667 42.666667h153.6l-226.133334 226.133333c-17.066667 17.066667-17.066667 42.666667 0 59.733334 8.533333 8.533333 17.066667 12.8 29.866667 12.8s21.333333-4.266667 29.866667-12.8L896 187.733333V341.333333c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666666-42.666667V85.333333c0-4.266667 0-12.8-4.266666-17.066666zM354.133333 610.133333L128 836.266667V682.666667c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666666 42.666667v256c0 4.266667 0 12.8 4.266666 17.066666 4.266667 8.533333 12.8 17.066667 21.333334 21.333334 4.266667 4.266667 12.8 4.266667 17.066666 4.266666h256c25.6 0 42.666667-17.066667 42.666667-42.666666s-17.066667-42.666667-42.666667-42.666667H187.733333l226.133334-226.133333c17.066667-17.066667 17.066667-42.666667 0-59.733334s-42.666667-17.066667-59.733334 0z" p-id="8645"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M6.25 3.55664C6.11193 3.55664 6 3.66857 6 3.80664V4.63997C6 4.77805 6.11193 4.88997 6.25 4.88997H11.0833C11.2214 4.88997 11.3333 4.77805 11.3333 4.63997V3.80664C11.3333 3.66857 11.2214 3.55664 11.0833 3.55664H6.25Z" />
<path d="M6 8.02878C6 7.89071 6.11193 7.77878 6.25 7.77878H13.0833C13.2214 7.77878 13.3333 7.89071 13.3333 8.02878V8.86211C13.3333 9.00018 13.2214 9.11211 13.0833 9.11211H6.25C6.11193 9.11211 6 9.00018 6 8.86211V8.02878Z" />
<path d="M6.25 12.0009C6.11193 12.0009 6 12.1128 6 12.2509V13.0842C6 13.2223 6.11193 13.3342 6.25 13.3342H15.0833C15.2214 13.3342 15.3333 13.2223 15.3333 13.0842V12.2509C15.3333 12.1128 15.2214 12.0009 15.0833 12.0009H6.25Z" />
<path d="M5.03981 14.5684C4.9773 14.6309 4.89251 14.666 4.80411 14.666H4.19677C4.153 14.666 4.10965 14.6574 4.06921 14.6406C4.02877 14.6239 3.99202 14.5993 3.96107 14.5684C3.93012 14.5374 3.90557 14.5007 3.88881 14.4602C3.87206 14.4198 3.86344 14.3765 3.86344 14.3327L3.86344 3.83902L2.39244 5.37235C2.33134 5.43523 2.24792 5.47151 2.16026 5.47332C2.0726 5.47513 1.98775 5.44232 1.92411 5.38202L1.43711 4.92068C1.40532 4.89057 1.37977 4.85449 1.36193 4.8145C1.34409 4.77452 1.3343 4.73141 1.33313 4.68764C1.33195 4.64387 1.33941 4.6003 1.35508 4.55941C1.37075 4.51852 1.39432 4.48112 1.42444 4.44935L3.98677 1.70768C4.40144 1.27001 5.13744 1.56335 5.13744 2.16602L5.13744 14.3327C5.13744 14.4211 5.10232 14.5059 5.03981 14.5684Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M6.25 11.1222C6.11193 11.1222 6 11.2341 6 11.3722V12.2055C6 12.3436 6.11193 12.4555 6.25 12.4555H11.0833C11.2214 12.4555 11.3333 12.3436 11.3333 12.2055V11.3722C11.3333 11.2341 11.2214 11.1222 11.0833 11.1222H6.25Z" />
<path d="M6 7.1478C6 7.00973 6.11193 6.8978 6.25 6.8978H13.0833C13.2214 6.8978 13.3333 7.00973 13.3333 7.1478V7.98113C13.3333 8.1192 13.2214 8.23113 13.0833 8.23113H6.25C6.11193 8.23113 6 8.1192 6 7.98113V7.1478Z" />
<path d="M6.25 2.67773C6.11193 2.67773 6 2.78966 6 2.92773V3.76107C6 3.89914 6.11193 4.01107 6.25 4.01107H15.0833C15.2214 4.01107 15.3333 3.89914 15.3333 3.76107V2.92773C15.3333 2.78966 15.2214 2.67773 15.0833 2.67773H6.25Z" />
<path d="M3.98898 14.4564C4.40365 14.8941 5.13965 14.6007 5.13965 13.9981L5.13965 1.83139C5.13965 1.74298 5.10453 1.6582 5.04202 1.59569C4.9795 1.53317 4.89472 1.49806 4.80632 1.49806H4.13965C4.05124 1.49806 3.96646 1.53317 3.90395 1.59569C3.84143 1.6582 3.80632 1.74298 3.80632 1.83139L3.80632 12.3247L2.39432 10.7977C2.36423 10.7659 2.32816 10.7403 2.28819 10.7225C2.24822 10.7046 2.20511 10.6948 2.16134 10.6936C2.11757 10.6924 2.07399 10.6998 2.03309 10.7154C1.9922 10.7311 1.95478 10.7546 1.92298 10.7847L1.43932 11.2434C1.4075 11.2735 1.38193 11.3095 1.36406 11.3495C1.34619 11.3895 1.33637 11.4326 1.33517 11.4764C1.33396 11.5201 1.34139 11.5637 1.35703 11.6046C1.37267 11.6455 1.39621 11.6829 1.42631 11.7147L3.98898 14.4564Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -42,6 +42,10 @@ export default {
}
},
time: {
dropdown_display_must: 'The display style of the current component is tiled. If it is not mandatory, the display style of the component will switch to dropdown display',
end_time_start_time: 'The end time must be greater than or equal to the start time',
passing_parameters: 'Empty data does not support passing parameters',
not_supported: 'After binding parameters, passing empty data is not supported',
set_time_filtering_range: 'Set time filtering range',
filter_range: 'The default value is outside the date filtering range, please reset it!',
interval_type: 'Interval type',
@ -599,7 +603,14 @@ export default {
datasource: 'Datasource',
table: 'Table',
creator: 'Creator',
createTime: 'Create Time'
createTime: 'Create Time',
operation: 'Operation',
operator: 'Operator',
operate_time: 'Operate Time',
modify: 'Modify',
show: 'Show',
delete: 'Delete',
show_data: 'Show Data'
},
data: {
confirm_delete: 'Confirm delete?'
@ -608,7 +619,8 @@ export default {
confirm_enable: 'Confirm enable task?',
confirm_disable: 'Confirm disable task?'
},
on_the_left: 'Please select a form on the left'
on_the_left: 'Please select a form on the left',
search_by_commit_name: 'Search by operator name'
},
detabs: {
custom_sort: 'Custom Sort',
@ -1534,6 +1546,7 @@ export default {
value_formatter_thousand_separator: 'Thousand Separator',
value_formatter_example: 'Example',
value_suffix: 'Value Suffix',
axis_label_length_limit: 'Length limit',
unit_none: 'None',
unit_thousand: 'Thousand',
unit_ten_thousand: 'Ten Thousand',
@ -1680,6 +1693,7 @@ export default {
map_line_color_target_color: 'End Color',
map_line_theta_offset: 'Radian',
gauge_axis_label: 'Axis Label',
gauge_percentage_tick: 'Percentage tick',
word_size_range: 'Word Size Range',
word_spacing: 'Word Spacing',
axis_multi_select_tip: 'Hold down the Ctrl/Cmd or Shift key and click to select more than one',
@ -2877,7 +2891,7 @@ export default {
chart_data: 'View data',
panel_preview: 'Preview report',
preview: 'Preview',
emial_preview: 'Report preview',
email_preview: 'Report preview',
chart_data_range: 'View data range',
panel_format: 'Panel format',
simple_repeat: 'Simple repeat',

View File

@ -42,6 +42,10 @@ export default {
}
},
time: {
dropdown_display_must: '當前組件的展示風格為平鋪,如果設為非必填,那麼組件的展示風格將切換為下拉展示。',
end_time_start_time: '結束時間必須大於或等於開始時間',
passing_parameters: '空數據不支持傳參數',
not_supported: '綁定參數後,不支持傳空數據',
set_time_filtering_range: '設定時間篩選範圍',
filter_range: '預設值超出日期篩選範圍內,請重新設定!',
interval_type: '區間類型',
@ -599,7 +603,14 @@ export default {
datasource: '數據源',
table: '數據庫表',
creator: '創建人',
createTime: '創建時間'
createTime: '創建時間',
operation: '操作',
operator: '操作人',
operate_time: '操作時間',
modify: '修改',
show: '查看',
delete: '刪除',
show_data: '查看數據'
},
data: {
confirm_delete: '確認刪除?'
@ -608,7 +619,9 @@ export default {
confirm_enable: '確認啟動任務?(單次任務會新建下發任務)',
confirm_disable: '確認停止任務?'
},
on_the_left: '請在左側選擇表單'
on_the_left: '請在左側選擇表單',
search_by_commit_name: '根據操作人名稱搜索'
},
detabs: {
custom_sort: '自定義排序',
@ -1531,6 +1544,7 @@ export default {
value_formatter_suffix: '單位後綴',
value_formatter_thousand_separator: '千分符',
value_formatter_example: '示例',
axis_label_length_limit: '長度限制',
unit_none: '無',
unit_thousand: '千',
unit_ten_thousand: '萬',
@ -1672,6 +1686,7 @@ export default {
map_line_color_target_color: '結束顏色',
map_line_theta_offset: '弧度',
gauge_axis_label: '刻度標籤',
gauge_percentage_tick: '百分比刻度',
word_size_range: '字號區間',
word_spacing: '文字間隔',
axis_multi_select_tip: '按住 Ctrl/Cmd 鍵或者 Shift 鍵再點擊可多選',
@ -2869,7 +2884,7 @@ export default {
chart_data: '視圖數據',
panel_preview: '預覽報告',
preview: '預覽',
emial_preview: '報告預覽',
email_preview: '報告預覽',
chart_data_range: '視圖數據範圍',
panel_format: '儀表板格式',
simple_repeat: '簡單重複',

View File

@ -46,6 +46,10 @@ export default {
upload_limit_size: '图片大小不超过'
},
time: {
dropdown_display_must: '当前组件的展示风格为平铺,如果设为非必填,那么组件的展示风格将切换为下拉展示。',
end_time_start_time: '结束时间必须大于或等于开始时间',
passing_parameters: '空数据不支持传参数',
not_supported: '空数据不支持传参数',
set_time_filtering_range: '设置时间筛选范围',
filter_range: '默认值超出日期筛选范围内,请重新设置!',
interval_type: '区间类型',
@ -598,7 +602,14 @@ export default {
datasource: '数据源',
table: '数据库表',
creator: '创建人',
createTime: '创建时间'
createTime: '创建时间',
operation: '操作',
operator: '操作人',
operate_time: '操作时间',
modify: '修改',
show: '查看',
delete: '删除',
show_data: '查看数据'
},
data: {
confirm_delete: '确认删除?'
@ -607,7 +618,8 @@ export default {
confirm_enable: '确认启动任务?(单次任务会新建下发任务)',
confirm_disable: '确认停止任务?'
},
on_the_left: '请在左侧选择表单'
on_the_left: '请在左侧选择表单',
search_by_commit_name: '根据操作人名称搜索'
},
detabs: {
custom_sort: '自定义排序',
@ -1531,6 +1543,7 @@ export default {
value_formatter_suffix: '单位后缀',
value_formatter_thousand_separator: '千分符',
value_formatter_example: '示例',
axis_label_length_limit: '长度限制',
unit_none: '无',
unit_thousand: '千',
unit_ten_thousand: '万',
@ -1672,6 +1685,7 @@ export default {
map_line_color_target_color: '结束颜色',
map_line_theta_offset: '弧度',
gauge_axis_label: '刻度标签',
gauge_percentage_tick: '百分比刻度',
word_size_range: '字号区间',
word_spacing: '文字间隔',
axis_multi_select_tip: '按住 Ctrl/Cmd 键或者 Shift 键再点击可多选',
@ -2872,7 +2886,7 @@ export default {
chart_data: '视图数据',
panel_preview: '预览报告',
preview: '预览',
emial_preview: '报告预览',
email_preview: '报告预览',
chart_data_range: '视图数据范围',
panel_format: '仪表板格式',
simple_repeat: '简单重复',

View File

@ -10,7 +10,8 @@ export default {
},
data() {
return {
aiDialogShow: false
aiDialogShow: false,
sizeState: 'min'
}
},
mounted() {
@ -22,6 +23,9 @@ export default {
},
closeAi() {
this.aiDialogShow = false
},
sizeChange() {
this.sizeState = this.sizeState === 'min' ? 'max' : 'min'
}
}
}
@ -29,10 +33,19 @@ export default {
<template>
<div
class="ai-main"
:class="{ 'ai-main-active': aiDialogShow }"
:class="{'ai-main-active': aiDialogShow,
'ai-main-active-max' : aiDialogShow && sizeState=== 'max',
'ai-main-active-min' : aiDialogShow && sizeState=== 'min'}"
>
<div class="ai-content">
<div class="close"><i @click="closeAi" class="el-icon-close" /></div>
<div class="close"><i
class="el-icon-close"
@click="closeAi"
/></div>
<div class="size-class"> <svg-icon
:icon-class="'dv-ai-window-'+sizeState"
@click="sizeChange"
/></div>
<iframe
:src="baseUrl"
style="width: 100%; height: 100%"
@ -48,12 +61,9 @@ export default {
position: fixed;
border-radius: 5px;
overflow: hidden;
height: 0;
bottom: 48px;
right: 36px;
height: 0;
width: 25%;
min-width: 350px;
max-width: 420px;
transition: 0.2s;
z-index: 10;
.ai-content {
@ -65,15 +75,37 @@ export default {
right: 12px;
top: 12px;
font-size: 24px;
color: #1a1a1a;
color: rgb(100, 106, 115);
cursor: pointer;
}
.size-class{
position: absolute;
right: 48px;
font-size: 16px;
top: 17px;
color: rgb(100, 106, 115);
cursor: pointer;
}
}
}
.ai-main-active {
border: 1px solid #d9d9d9;
}
.ai-main-active-min {
min-width: 350px;
max-width: 420px;
height: 50%;
width: 25%;
min-height: 450px;
max-height: 600px;
bottom: 48px;
right: 36px;
}
.ai-main-active-max {
height: 100%;
width: 50%;
bottom: 0px;
right: 0px;
}
</style>

View File

@ -154,6 +154,7 @@ const data = {
},
previewVisible: false,
previewComponentData: [],
sourceComponentData: [],
currentCanvasNewId: [],
lastViewRequestInfo: {},
multiplexingStyleAdapt: true, // 复用样式跟随主题
@ -191,6 +192,7 @@ const data = {
if (style) {
style['selfAdaption'] = true
}
style.panel['alpha'] = style.panel['alpha'] === undefined ? 100 : style.panel['alpha']
state.canvasStyleData = style
},
@ -261,6 +263,9 @@ const data = {
setPreviewComponentData(state, previewComponentData = []) {
Vue.set(state, 'previewComponentData', previewComponentData)
},
setSourceComponentData(state, sourceComponentData = []) {
Vue.set(state, 'sourceComponentData', sourceComponentData)
},
setComponentViewsData(state, componentViewsData = {}) {
Vue.set(state, 'componentViewsData', componentViewsData)
},
@ -539,6 +544,10 @@ const data = {
if (element.options.manualModify) {
element.options.manualModify = false
}
// 去掉动态时间
if (element.options.attrs?.default?.isDynamic) {
element.options.attrs.default.isDynamic = false
}
// 去掉首选项
if (element.options?.attrs?.selectFirst) {
element.options.attrs.selectFirst = false

View File

@ -833,7 +833,7 @@ div:focus {
color: #1F2329 !important;
}
.el-radio__input.is-checked:not(.is-disabled)+.el-radio__label {
.el-radio:not(.is-custom-select) .el-radio__input.is-checked:not(.is-disabled)+.el-radio__label {
color: var(--deTextPrimary, #1F2329) !important;
}

View File

@ -0,0 +1,27 @@
import { deepCopy } from '@/components/canvas/utils/utils'
export default function treeSort(tree, hisSortType, sortType) {
const result = deepCopy(tree)
sortCircle(result, hisSortType, sortType)
return result
}
export function sortCircle(tree, hisSortType, sortType) {
sortPer(tree, hisSortType, sortType)
tree.forEach(node => {
if (node.children && node.children.length > 0) {
sortPer(node.children, hisSortType, sortType)
}
})
return tree
}
export function sortPer(subTree, hisSortType, sortType) {
if (sortType === 'name_desc') {
subTree.sort((a, b) => b.name.localeCompare(a.name, 'zh-Hans-CN', { sensitivity: 'accent' }))
} else if (sortType === 'name_asc') {
subTree.sort((a, b) => a.name.localeCompare(b.name, 'zh-Hans-CN', { sensitivity: 'accent' }))
} else if (sortType === 'time_asc') {
subTree.reverse()
}
}

View File

@ -236,7 +236,7 @@
</el-col>
</el-row>
<template v-if="this.curComponent.component === 'de-select' && !this.curComponent.options.attrs.multiple">
<template v-if="this.curComponent.component === 'de-select' && !this.curComponent.options.attrs.multiple && this.curComponent.options.attrs.required">
<el-row
style="height: 40px;overflow: hidden;"
>
@ -299,6 +299,7 @@
<el-input-number
v-model="curComponent.style.showNum"
:min="1"
step-strictly
:max="10"
controls-position="right"
size="small"

View File

@ -11,7 +11,8 @@ import {
getAnalyse,
setGradientColor,
getMeta,
configPlotTooltipEvent
configPlotTooltipEvent,
configAxisLabelLengthLimit
} from '@/views/chart/chart/common/common_antv'
import { antVCustomColor, getColors, handleEmptyDataStrategy, hexColorToRGBA } from '@/views/chart/chart/util'
import { cloneDeep, find } from 'lodash-es'
@ -251,8 +252,10 @@ export function hBaseBarOptionAntV(container, chart, action, isGroup, isStack) {
const plot = new Bar(container, options)
plot.on('interval:click', action)
// 处理 tooltip 被其他视图遮挡
// 处理 tooltip 被其他视图遮挡
configPlotTooltipEvent(chart, plot)
// 处理纵轴标签长度限制
configAxisLabelLengthLimit(chart, plot)
return plot
}

View File

@ -124,6 +124,7 @@ export const DEFAULT_SIZE = {
gaugeEndAngle: -45,
gaugeAxisLine: true,
gaugeTickCount: 5,
gaugePercentLabel: true,
dimensionFontSize: 18,
quotaFontSize: 18,
spaceSplit: 10,
@ -385,7 +386,8 @@ export const DEFAULT_YAXIS_STYLE = {
color: '#333333',
fontSize: '12',
rotate: 0,
formatter: '{value}'
formatter: '{value}',
lengthLimit: 20
},
axisLine: {
show: false,

View File

@ -12,6 +12,10 @@ import {
regressionPow,
regressionQuad
} from 'd3-regression/dist/d3-regression.esm'
import substitute from '@antv/util/esm/substitute'
import createDom from '@antv/dom-util/esm/create-dom'
import { assign } from 'lodash-es'
export function getPadding(chart) {
if (chart.drill) {
return [0, 10, 26, 10]
@ -849,7 +853,11 @@ export function getYAxis(chart) {
return valueFormatter(value, a.axisLabelFormatter)
}
} else {
return value
const { lengthLimit } = a.axisLabel
if (!lengthLimit || value?.length <= lengthLimit) {
return value
}
return value?.slice(0, lengthLimit) + '...'
}
}
}
@ -1275,6 +1283,19 @@ const REGRESSION_ALGO_MAP = {
pow: regressionPow,
loess: regressionLoess
}
const AXIS_LABEL_TOOLTIP_STYLE = {
transition: 'left 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s, top 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s',
backgroundColor: 'rgb(255, 255, 255)',
boxShadow: 'rgb(174, 174, 174) 0px 0px 10px',
borderRadius: '3px',
padding: '8px 12px',
opacity: '0.95',
position: 'absolute',
visibility: 'visible'
}
const AXIS_LABEL_TOOLTIP_TPL = '<div class="g2-axis-label-tooltip">' +
'<div class="g2-tooltip-title">{title}</div>' +
'</div>'
export function configPlotTrendLine(chart, plot) {
const senior = JSON.parse(chart.senior)
if (!senior?.trendLine?.length || !chart.data?.data?.length) {
@ -1346,3 +1367,67 @@ export function configPlotTrendLine(chart, plot) {
regLine.render()
})
}
export function configAxisLabelLengthLimit(chart, plot) {
const customStyle = JSON.parse(chart.customStyle)
const { lengthLimit, fontSize, color, show } = customStyle.yAxis.axisLabel
if (!lengthLimit || !show) {
return
}
plot.on('axis-label:mouseenter', (e) => {
const field = e.target.cfg.delegateObject.component.cfg.field
// 先只处理竖轴
if (field !== 'field') {
return
}
const realContent = e.target.attrs.text
if (realContent.length < lengthLimit || !(realContent?.slice(-3) === '...')) {
return
}
const { x, y } = e
const parentNode = e.event.target.parentNode
let labelTooltipDom = parentNode.getElementsByClassName('g2-axis-label-tooltip')?.[0]
if (!labelTooltipDom) {
const title = e.target.cfg.delegateObject.item.name
const domStr = substitute(AXIS_LABEL_TOOLTIP_TPL, { title })
labelTooltipDom = createDom(domStr)
assign(labelTooltipDom.style, AXIS_LABEL_TOOLTIP_STYLE)
parentNode.appendChild(labelTooltipDom)
} else {
labelTooltipDom.getElementsByClassName('g2-tooltip-title')[0].innerHTML = e.target.cfg.delegateObject.item.name
labelTooltipDom.style.visibility = 'visible'
}
const { height, width } = parentNode.getBoundingClientRect()
const { offsetHeight, offsetWidth } = labelTooltipDom
if (offsetHeight > height || offsetWidth > width) {
labelTooltipDom.style.left = labelTooltipDom.style.top = `0px`
return
}
const initPosition = { left: x + 10, top: y + 15 }
if (initPosition.left + offsetWidth > width) {
initPosition.left = width - offsetWidth - 10
}
if (initPosition.top + offsetHeight > height) {
initPosition.top -= (offsetHeight + 15)
}
labelTooltipDom.style.left = `${initPosition.left}px`
labelTooltipDom.style.top = `${initPosition.top}px`
labelTooltipDom.style.color = color
labelTooltipDom.style.fontSize = `${fontSize}px`
})
plot.on('axis-label:mouseleave', (e) => {
const field = e.target.cfg.delegateObject.component.cfg.field
// 先只处理竖轴
if (field !== 'field') {
return
}
const realContent = e.target.attrs.text
if (realContent.length < lengthLimit || !(realContent?.slice(-3) === '...')) {
return
}
const parentNode = e.event.target.parentNode
let labelTooltipDom = parentNode.getElementsByClassName('g2-axis-label-tooltip')?.[0]
if (labelTooltipDom) {
labelTooltipDom.style.visibility = 'hidden'
}
})
}

View File

@ -41,6 +41,7 @@ export function baseFunnelOptionAntV(container, chart, action) {
tooltip: tooltip,
legend: legend,
conversionTag,
maxSize: conversionTag ? 0.8 : 1,
interactions: [
{
type: 'legend-active', cfg: {

View File

@ -2,7 +2,8 @@ import { getPadding, getTheme, setGradientColor } from '@/views/chart/chart/comm
import { Gauge } from '@antv/g2plot'
import { DEFAULT_LABEL, DEFAULT_SIZE, DEFAULT_THRESHOLD } from '@/views/chart/chart/chart'
import { getScaleValue } from '@/components/canvas/utils/style'
import { valueFormatter } from '@/views/chart/chart/formatter'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import { parseJson } from '@/views/chart/chart/util'
let labelFormatter = null
@ -14,14 +15,6 @@ export function baseGaugeOptionAntV(container, chart, action, scale = 1) {
const data = chart.data.series[0].data[0]
// size
let customAttr = {}
let axisLabel = {
style: {
fontSize: getScaleValue(14, scale) // 刻度值字体大小
},
formatter: function(v) {
return v === '0' ? v : (v * 100 + '%')
}
}
if (chart.customAttr) {
customAttr = JSON.parse(chart.customAttr)
if (customAttr.size) {
@ -41,11 +34,26 @@ export function baseGaugeOptionAntV(container, chart, action, scale = 1) {
}
startAngel = parseInt(size.gaugeStartAngle) * Math.PI / 180
endAngel = parseInt(size.gaugeEndAngle) * Math.PI / 180
if (customAttr.size.gaugeAxisLine === false) {
axisLabel = false
}
}
}
let axisLabel = {
style: {
fontSize: getScaleValue(14, scale) // 刻度值字体大小
},
formatter: function(v) {
const gaugePercentLabel = customAttr?.size?.gaugePercentLabel
if (gaugePercentLabel === false) {
const yAxis = parseJson(chart.yaxis)?.[0]
const formatter = yAxis?.formatterCfg ?? formatterItem
const val = v === '0' ? min : v === '1' ? max : min + (max - min) * v
return valueFormatter(val, formatter)
}
return v === '0' ? v : (v * 100 + '%')
}
}
if (customAttr.size.gaugeAxisLine === false) {
axisLabel = false
}
const per = (parseFloat(data) - parseFloat(min)) / (parseFloat(max) - parseFloat(min))
// label
if (customAttr.label) {

View File

@ -31,6 +31,7 @@ export function basePieOptionAntV(container, chart, action) {
label: label,
tooltip: tooltip,
legend: legend,
animation: false,
pieStyle: {
lineWidth: 0
},

View File

@ -182,38 +182,7 @@ export function baseTableInfo(container, chart, action, tableData, pageInfo, vue
}
// 表头排序
if (customAttr.size.tableHeaderSort) {
const sortIconMap = {
'asc': 'SortUp',
'desc': 'SortDown'
}
s2Options.headerActionIcons = [
{
iconNames: ['GroupAsc', 'SortUp', 'SortDown'],
belongsCell: 'colCell',
displayCondition: (meta, iconName) => {
if (meta.field === SERIES_NUMBER_FIELD) {
return false
}
const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap')
const sortType = sortMethodMap?.[meta.field]
if (sortType) {
return iconName === sortIconMap[sortType]
}
return iconName === 'GroupAsc'
},
onClick: (props) => {
const { meta, event } = props
meta.spreadsheet.showTooltip({
position: {
x: event.clientX,
y: event.clientY
},
event,
...props
})
}
}
]
configHeaderSort(chart, s2Options)
}
// 开启序号之后,第一列就是序号列,修改 label 即可
if (s2Options.showSeriesNumber) {
@ -426,38 +395,7 @@ export function baseTableNormal(container, chart, action, tableData, vueCom, res
}
// 表头排序
if (customAttr.size.tableHeaderSort) {
const sortIconMap = {
'asc': 'SortUp',
'desc': 'SortDown'
}
s2Options.headerActionIcons = [
{
iconNames: ['GroupAsc', 'SortUp', 'SortDown'],
belongsCell: 'colCell',
displayCondition: (meta, iconName) => {
if (meta.field === SERIES_NUMBER_FIELD) {
return false
}
const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap')
const sortType = sortMethodMap?.[meta.field]
if (sortType) {
return iconName === sortIconMap[sortType]
}
return iconName === 'GroupAsc'
},
onClick: (props) => {
const { meta, event } = props
meta.spreadsheet.showTooltip({
position: {
x: event.clientX,
y: event.clientY
},
event,
...props
})
}
}
]
configHeaderSort(chart, s2Options)
}
// 开启序号之后,第一列就是序号列,修改 label 即可
if (s2Options.showSeriesNumber) {
@ -809,9 +747,14 @@ function getConditions(chart) {
res.text.push({
field: field.field.dataeaseName,
mapping(value, rowData) {
// 总计小计
if (rowData?.isTotals) {
return null
}
// 表头
if (rowData?.id && rowData?.field === rowData.id) {
return null
}
return {
fill: mappingColor(value, defaultTextColor, field, 'color', filedValueMap, rowData)
}
@ -823,6 +766,9 @@ function getConditions(chart) {
if (rowData?.isTotals) {
return null
}
if (rowData?.id && rowData?.field === rowData.id) {
return null
}
const fill = mappingColor(value, defaultBgColor, field, 'backgroundColor', filedValueMap, rowData)
if (fill) {
return { fill }
@ -1211,3 +1157,70 @@ function copyContent(s2Instance, event, fieldMeta) {
copyString(content, true)
}
}
const SORT_DEFAULT = '<svg t="1711681787276" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4355" width="200" height="200"><path d="M922.345786 372.183628l-39.393195 38.687114L676.138314 211.079416l0 683.909301-54.713113 0L621.425202 129.010259l53.320393 0L922.345786 372.183628zM349.254406 894.989741 101.654214 651.815349l39.393195-38.687114 206.814276 199.792349L347.861686 129.010259l54.713113 0 0 765.978459L349.254406 894.988718z" fill="{fill}" p-id="4356"></path></svg>'
const SORT_UP = '<svg t="1711682928245" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11756" width="200" height="200"><path d="M960 704L512 256 64 704z" fill="{fill}" p-id="11757"></path></svg>'
const SORT_DOWN = '<svg t="1711681879346" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4655" width="200" height="200"><path d="M64 320l448 448 448-448z" fill="{fill}" p-id="4656"></path></svg>'
function configHeaderSort(chart, options) {
const { tableHeaderFontColor } = JSON.parse(chart.customAttr).color
const iconColor = tableHeaderFontColor ?? '#666'
const sortDefault = svg2Base64(SORT_DEFAULT.replace('{fill}', iconColor))
const sortUp = svg2Base64(SORT_UP.replace('{fill}', iconColor))
const sortDown = svg2Base64(SORT_DOWN.replace('{fill}', iconColor))
const randomSuffix = Math.random()
const sortIconMap = {
'asc': `customSortUp${randomSuffix}`,
'desc': `customSortDown${randomSuffix}`
}
options.customSVGIcons = [
{
name: `customSortDefault${randomSuffix}`,
svg: sortDefault
},
{
name: `customSortUp${randomSuffix}`,
svg: sortUp
},
{
name: `customSortDown${randomSuffix}`,
svg: sortDown
}
]
options.headerActionIcons = [
{
iconNames: [
`customSortDefault${randomSuffix}`,
`customSortUp${randomSuffix}`,
`customSortDown${randomSuffix}`
],
belongsCell: 'colCell',
displayCondition: (meta, iconName) => {
if (meta.field === SERIES_NUMBER_FIELD) {
return false
}
const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap')
const sortType = sortMethodMap?.[meta.field]
if (sortType) {
return iconName === sortIconMap[sortType]
}
return iconName === `customSortDefault${randomSuffix}`
},
onClick: (props) => {
const { meta, event } = props
meta.spreadsheet.showTooltip({
position: {
x: event.clientX,
y: event.clientY
},
event,
...props
})
}
}
]
}
function svg2Base64(svg) {
return `data:image/svg+xml;charset=utf-8;base64,${btoa(svg)}`
}

View File

@ -323,7 +323,8 @@ export const TYPE_CONFIGS = [
'gaugeStartAngle',
'gaugeEndAngle',
'gaugeTickCount',
'gaugeAxisLine'
'gaugeAxisLine',
'gaugePercentLabel'
],
'label-selector-ant-v': [
'labelGauge'
@ -1082,7 +1083,8 @@ export const TYPE_CONFIGS = [
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
'axisLabel',
'axisLabelLength'
],
'title-selector-ant-v': [
'show',
@ -1241,7 +1243,8 @@ export const TYPE_CONFIGS = [
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
'axisLabel',
'axisLabelLength'
],
'title-selector-ant-v': [
'show',
@ -1317,7 +1320,8 @@ export const TYPE_CONFIGS = [
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
'axisLabel',
'axisLabelLength'
],
'title-selector-ant-v': [
'show',
@ -3932,3 +3936,26 @@ export function parseJson(target) {
}
return JSON.parse(JSON.stringify(target))
}
export function adjustPosition(targetDom, parentDom, clickPosition, offset, initSize) {
const { clientHeight: targetHeight, clientWidth: targetWidth } = targetDom
const { clientHeight: parentHeight, clientWidth: parentWidth } = parentDom
const { x, y } = clickPosition
const { x: offsetX, y: offsetY } = offset
const result = {
x: offsetX ? x + offsetX : x,
y: offsetY ? y + offsetY : y
}
const width = targetWidth ? targetWidth : initSize.width
const height = targetHeight ? targetHeight : initSize.height
if ( result.x + width > parentWidth ) {
result.x = parentWidth - width
}
if (result.y + height > parentHeight) {
result.y = parentHeight - height
}
if (result.y - height < 0) {
result.y = height
}
return result
}

View File

@ -32,6 +32,7 @@
</div>
</span>
<div
ref="chart"
:id="chartId"
style="width: 100%;overflow: hidden;"
:style="{height:chartHeight}"
@ -43,7 +44,7 @@
import { baseLiquid } from '@/views/chart/chart/liquid/liquid'
import { uuid } from 'vue-uuid'
import ViewTrackBar from '@/components/canvas/components/editor/ViewTrackBar'
import { getRemark, hexColorToRGBA } from '@/views/chart/chart/util'
import { adjustPosition, getRemark, hexColorToRGBA } from '@/views/chart/chart/util'
import { baseBarOptionAntV, hBaseBarOptionAntV, baseBidirectionalBarOptionAntV, timeRangeBarOptionAntV } from '@/views/chart/chart/bar/bar_antv'
import { baseAreaOptionAntV, baseLineOptionAntV } from '@/views/chart/chart/line/line_antv'
import { basePieOptionAntV, basePieRoseOptionAntV } from '@/views/chart/chart/pie/pie_antv'
@ -345,9 +346,27 @@ export default {
}
if (this.trackMenu.length < 2) { //
this.trackClick(this.trackMenu[0])
} else { //
this.trackBarStyle.left = param.x + 'px'
this.trackBarStyle.top = (param.y + 10) + 'px'
} else {
//
const menuDom = this.$refs.viewTrack.$el.getElementsByClassName("track-menu")?.[0]
const chartDom = this.$refs.chart
let position = {
x: param.x,
y: param.y
}
const offset = {
x: 0,
y: 10
}
const initSize = {
width: 80,
height: 76
}
if (menuDom && chartDom) {
position = adjustPosition(menuDom, chartDom, param, offset, initSize)
}
this.trackBarStyle.left = position.x + 'px'
this.trackBarStyle.top = position.y + 'px'
this.$refs.viewTrack.trackButtonClick()
}
},

View File

@ -331,11 +331,8 @@ export default {
if (this.chart.type === 'table-pivot') {
rowData = { ...meta.rowQuery, ...meta.colQuery }
rowData[meta.valueField] = meta.fieldValue
} else if (this.showPage && (this.chart.datasetMode === 1 || (this.chart.datasetMode === 0 && this.not_support_page_dataset.includes(this.chart.datasourceType)))) {
const rowIndex = (this.currentPage.page - 1) * this.currentPage.pageSize + meta.rowIndex
rowData = this.chart.data.tableRow[rowIndex]
} else {
rowData = this.chart.data.tableRow[meta.rowIndex]
rowData = this.myChart.dataSet.getRowData(meta)
}
const dimensionList = []
for (const key in rowData) {

View File

@ -265,6 +265,20 @@
@change="changeYAxisStyle('axisLabel')"
/>
</el-form-item>
<el-form-item
v-show="showProperty('axisLabelLength')"
:label="$t('chart.axis_label_length_limit')"
class="form-item"
>
<el-input-number
v-model="axisForm.axisLabel.lengthLimit"
:precision="0"
:min="1"
:max="50"
size="mini"
@change="changeYAxisStyle('axisLabel')"
/>
</el-form-item>
<el-form-item
:label="$t('chart.axis_label_rotate')"
class="form-item form-item-slider"
@ -457,6 +471,7 @@ export default {
if (!this.axisForm.splitLine.dashStyle) {
this.axisForm.splitLine.dashStyle = JSON.parse(JSON.stringify(DEFAULT_YAXIS_STYLE.splitLine.dashStyle))
}
this.axisForm.axisLabel.lengthLimit = this.axisForm.axisLabel.lengthLimit ?? DEFAULT_YAXIS_STYLE.axisLabel.lengthLimit
}
}
},

View File

@ -216,7 +216,7 @@
<span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item>
<el-dropdown-item
v-if="chart.render === 'antv' && chart.type !== 'gauge' && chart.type !== 'liquid' && chart.type !== 'bar-time-range'"
v-if="chart.render === 'antv' && chart.type !== 'liquid' && chart.type !== 'bar-time-range'"
icon="el-icon-notebook-2"
divided
:command="beforeClickItem('formatter')"

View File

@ -384,9 +384,13 @@
<span style="display: inline"> {{ item.enumValues.join(',') }}</span>
<el-tooltip
v-if="item.enumValues && item.enumValues.length"
:content="item.enumValues.join(',')"
>
<i class="el-icon-info"></i>
<template v-slot:content>
<div style="max-width: 200px">
{{ item.enumValues.join(',') }}
</div>
</template>
</el-tooltip>
</div>
</el-col>

View File

@ -719,7 +719,7 @@ export default {
const fieldType = this.getFieldType(fieldId)
if (fieldType) {
post('/chart/view/getFieldData/' + this.chart.id + '/' + this.panelInfo.id + '/' + fieldId + '/' + fieldType, {}).then(response => {
this.$set(this.fieldEnumValues, fieldId, response.data)
this.$set(this.fieldEnumValues, fieldId, response.data?.filter(i => i && i.trim()))
})
}
},

View File

@ -916,6 +916,16 @@
@change="changeBarSizeCase('gaugeAxisLine')"
/>
</el-form-item>
<el-form-item
v-if="showProperty('gaugePercentLabel') && sizeForm.gaugeAxisLine"
:label="$t('chart.gauge_percentage_tick')"
class="form-item"
>
<el-checkbox
v-model="sizeForm.gaugePercentLabel"
@change="changeBarSizeCase('gaugePercentLabel')"
/>
</el-form-item>
<!-- <el-form-item v-if="showProperty('gaugeTickCount')" :label="$t('chart.tick_count')" class="form-item form-item-slider">-->
<!-- <el-input-number v-model="sizeForm.gaugeTickCount" :min="1" :step="1" :precision="0" size="mini" @change="changeBarSizeCase('gaugeTickCount')" />-->
<!-- </el-form-item>-->
@ -1837,7 +1847,7 @@ export default {
}
this.sizeForm.wordSizeRange = this.sizeForm.wordSizeRange ?? DEFAULT_SIZE.wordSizeRange
this.sizeForm.wordSpacing = this.sizeForm.wordSpacing ?? DEFAULT_SIZE.wordSpacing
this.sizeForm.gaugePercentLabel = this.sizeForm.gaugePercentLabel === false ? false : DEFAULT_SIZE.gaugePercentLabel
if (this.chart.type !== 'table-pivot') {
let { xaxis, yaxis } = this.chart
if (!(xaxis instanceof Object)) {

View File

@ -2569,6 +2569,9 @@ export default {
}
}
}
if (view.type === 'table-info' && ele.groupType === 'q') {
ele.compareCalc = compareItem
}
})
if (equalsAny(view.type, 'table-pivot', 'bar-group', 'bar-group-stack', 'flow-map', 'race-bar') ||
(view.render === 'antv' && (view.type === 'line' || view.type === 'scatter' || view.type === 'bar-time-range'))) {

View File

@ -1,5 +1,8 @@
<template>
<el-container class="DataFillingSave">
<el-container
v-loading="loading"
class="DataFillingSave"
>
<el-header class="de-header">
<div class="panel-info-area">
<span class="text16 margin-left12">
@ -126,7 +129,7 @@
style="padding-top: 28px; padding-bottom: 0"
>
<span
class="perfix"
class="prefix"
style="margin-bottom: 28px; "
>任务下发时间</span>
<el-form-item
@ -149,7 +152,7 @@
style="padding-top: 0; padding-bottom: 0"
>
<span
class="perfix"
class="prefix"
style="margin-bottom: 28px"
>填报截止时间</span>
<el-form-item
@ -218,12 +221,17 @@
<span class="tail">{{ $t('cron.every_exec') }}</span>
</div>
<div class="rate-type-time second-row">
<span class="perfix">在任务下发</span>
<span class="prefix">在任务下发</span>
<el-input-number
v-model.number="form.publishRangeTime"
class="w140"
min="1"
step="1"
:min="1"
:max="100"
:step="1"
:precision="0"
@change="onPublishRangeTimeChange(form)"
@blur="onPublishRangeTimeChange(form)"
@keyup.enter.native="onPublishRangeTimeChange(form)"
/>
<el-select
v-model="form.publishRangeTimeType"
@ -315,6 +323,7 @@ export default {
},
data() {
return {
loading: false,
showTable: false,
showMedia: false,
formType: 'add',
@ -544,6 +553,8 @@ export default {
},
save() {
this.loading = true
const request = this.form
request.rateType = -1
@ -604,8 +615,11 @@ export default {
saveFormTasks(this.formId, param.request).then(res => {
this.$emit('save-success')
}).finally(() => {
this.loading = false
})
} else {
this.loading = false
return false
}
})
@ -799,6 +813,13 @@ export default {
return callback(new Error('收件人、角色、组织至少选择一项'))
}
return callback()
},
onPublishRangeTimeChange(form) {
if (!form.publishRangeTime) {
this.$nextTick(() => {
form.publishRangeTime = 1
})
}
}
}
}
@ -930,7 +951,7 @@ export default {
width: 160px !important;
}
.perfix {
.prefix {
font-family: PingFang SC;
font-size: 14px;
font-weight: 400;

View File

@ -1,5 +1,5 @@
<script>
import { forEach, find, concat, cloneDeep } from 'lodash-es'
import { forEach, find, concat, cloneDeep, floor } from 'lodash-es'
import { PHONE_REGEX, EMAIL_REGEX } from '@/utils/validate'
import { newFormRowData, saveFormRowData, userFillFormData } from '@/views/dataFilling/form/dataFilling'
@ -60,6 +60,7 @@ export default {
callback()
}
return {
loading: false,
formData: {},
requiredRule: { required: true, message: this.$t('commons.required'), trigger: ['blur', 'change'] },
dateRangeRequiredRule: { validator: checkDateRangeRequireValidator, message: this.$t('commons.required'), trigger: ['blur', 'change'] },
@ -123,7 +124,19 @@ export default {
closeDrawer() {
this.$emit('update:showDrawer', false)
},
onNumberChange(item) {
let value
if (item.settings.mapping.type === 'number') {
value = floor(item.value, 0)
} else {
value = floor(item.value, 8)
}
this.$nextTick(() => {
item.value = value
})
},
doSave() {
this.loading = true
this.$refs['mForm'].validate((valid) => {
if (valid) {
const _data = {}
@ -156,20 +169,28 @@ export default {
if (this.userTaskId) {
userFillFormData(this.userTaskId, _data).then(res => {
this.$emit('save-success')
}).finally(() => {
this.loading = false
})
} else {
if (this.id !== undefined) {
// update
saveFormRowData(this.formId, this.id, _data).then(res => {
this.$emit('save-success')
}).finally(() => {
this.loading = false
})
} else {
// insert
newFormRowData(this.formId, _data).then(res => {
this.$emit('save-success')
}).finally(() => {
this.loading = false
})
}
}
} else {
this.loading = false
}
})
}
@ -179,7 +200,10 @@ export default {
</script>
<template>
<el-container class="DataFillingSave">
<el-container
v-loading="loading"
class="DataFillingSave"
>
<el-header class="de-header">
<div class="panel-info-area">
<span class="text16 margin-left12">
@ -235,6 +259,8 @@ export default {
:readonly="readonly"
:placeholder="item.settings.placeholder"
size="small"
:show-word-limit="item.value !== undefined && item.value.length > 250"
maxlength="255"
/>
<el-input-number
v-if="item.type === 'input' && item.settings.inputType === 'number'"
@ -244,7 +270,13 @@ export default {
:placeholder="item.settings.placeholder"
style="width: 100%"
controls-position="right"
:precision="item.settings.mapping.type === 'number' ? 0 : undefined"
size="small"
:min="-999999999999"
:max="999999999999"
@change="onNumberChange(item)"
@blur="onNumberChange(item)"
@keyup.enter.native="onNumberChange(item)"
/>
<el-input
v-else-if="item.type === 'textarea'"

View File

@ -181,7 +181,7 @@
</template>
</el-table-column>
<el-table-column
label="操作"
:label="$t('data_fill.form.operation')"
width="160"
fixed="right"
>
@ -190,19 +190,19 @@
type="text"
@click="updateRow(scope.row.data)"
>
修改
{{ $t('data_fill.form.modify') }}
</el-button>
<el-button
type="text"
@click="openRow(scope.row.data)"
>
查看
{{ $t('data_fill.form.show') }}
</el-button>
<el-button
type="text"
@click="deleteRow(scope.row.data[paginationConfig.key])"
>
删除
{{ $t('data_fill.form.delete') }}
</el-button>
</template>
</el-table-column>
@ -223,15 +223,16 @@
:offset="16"
>
<el-input
ref="search"
ref="search2"
v-model="operateName"
:placeholder="$t('user.search_by_name')"
:placeholder="$t('data_fill.search_by_commit_name')"
prefix-icon="el-icon-search"
class="name-email-search"
size="small"
clearable
@blur="searchTableRecordData"
@clear="searchTableRecordData"
@clear="entryKey('record')"
@keyup.enter.native="entryKey('record')"
/>
</el-col>
</el-row>
@ -251,7 +252,7 @@
<el-table-column
key="operate"
prop="operate"
label="操作"
:label="$t('data_fill.form.operation')"
>
<template slot-scope="scope">
<template v-if="scope.row.operate === 'INSERT'">
@ -271,7 +272,7 @@
<el-table-column
key="commitByName"
prop="commitByName"
label="操作人"
:label="$t('data_fill.form.operator')"
>
<template slot-scope="scope">
{{ scope.row.commitByName ? scope.row.commitByName: scope.row.commitBy }}
@ -280,7 +281,7 @@
<el-table-column
key="commitTime"
prop="commitTime"
label="操作时间"
:label="$t('data_fill.form.operate_time')"
>
<template slot-scope="scope">
{{ new Date(scope.row.commitTime).format("yyyy-MM-dd hh:mm:ss") }}
@ -288,7 +289,7 @@
</el-table-column>
<el-table-column
key="id"
label="操作"
:label="$t('data_fill.form.operation')"
prop="id"
>
<template slot-scope="scope">
@ -297,7 +298,7 @@
type="text"
@click="showData(scope.row)"
>
查看数据
{{ $t('data_fill.form.show_data') }}
</el-button>
</template>
</el-table-column>
@ -325,7 +326,7 @@
:offset="8"
>
<el-input
ref="search"
ref="search3"
v-model="taskName"
:placeholder="$t('commons.search_by_name')"
prefix-icon="el-icon-search"
@ -333,7 +334,8 @@
size="small"
clearable
@blur="searchFormTaskData"
@clear="searchFormTaskData"
@clear="entryKey('task')"
@keyup.enter.native="entryKey('task')"
/>
</el-col>
</el-row>
@ -400,7 +402,7 @@
</el-table-column>
<el-table-column
key="id"
label="操作"
:label="$t('data_fill.form.operation')"
prop="id"
>
<template slot-scope="scope">
@ -602,13 +604,31 @@ export default {
this.tasks = []
}
this.initTable(this.param.id)
},
tabActive: function(newVal, oldVal) {
this.resetPage()
if (newVal === 'record') {
this.searchTableRecordData()
} else if (newVal === 'task') {
this.searchFormTaskData()
} else {
this.searchTableData()
}
}
},
mounted() {
this.initTable(this.param.id)
},
methods: {
entryKey(type) {
if (type === 'record') {
this.$refs.search2.focus()
this.$refs.search2.blur()
} else if (type === 'task') {
this.$refs.search3.focus()
this.$refs.search3.blur()
}
},
initTable(id) {
this.resetPage()
this.searchTableData()
@ -636,7 +656,7 @@ export default {
obj[key] = undefined
}
} else {
obj[key] = value
obj[key] = value === null ? undefined : value
}
})
_data.push({
@ -659,7 +679,7 @@ export default {
},
searchFormTaskData() {
searchFormTasks(this.param.id, { name: this.taskName }, this.recordPaginationConfig.currentPage, this.recordPaginationConfig.pageSize).then(res => {
searchFormTasks(this.param.id, { name: this.taskName }, this.taskPaginationConfig.currentPage, this.taskPaginationConfig.pageSize).then(res => {
if (res.data) {
this.taskPaginationConfig.total = res.data.itemCount
this.tasks = res.data.listObject
@ -696,7 +716,7 @@ export default {
taskHandleSizeChange(pageSize) {
this.taskPaginationConfig.currentPage = 1
this.taskPaginationConfig.pageSize = pageSize
this.searchTableRecordData()
this.searchFormTaskData()
},
taskHandleCurrentChange(currentPage) {
this.taskPaginationConfig.currentPage = currentPage
@ -712,6 +732,7 @@ export default {
resetPage() {
this.operateName = ''
this.taskName = ''
this.paginationConfig = {
currentPage: 1,
pageSize: 10,
@ -734,12 +755,12 @@ export default {
/* if (this.tabActive === 'dataPreview') {
this.initTable(this.param.id)
}*/
if (this.tabActive === 'record') {
/* if (this.tabActive === 'record') {
this.searchTableRecordData()
}
if (this.tabActive === 'task') {
this.searchFormTaskData()
}
}*/
},
showData(row) {

View File

@ -312,6 +312,9 @@ export default {
item.value = []
} else {
item.value = undefined
if (item.settings.mapping.type === 'text') {
item.settings.mapping.type = undefined
}
}
},
getRules(item) {
@ -556,6 +559,7 @@ export default {
>
<el-input
v-if="item.type === 'input' && item.settings.inputType !== 'number'"
:key="item.id + item.settings.inputType"
v-model="item.value"
:type="item.settings.inputType"
:required="item.settings.required"
@ -564,6 +568,7 @@ export default {
/>
<el-input-number
v-if="item.type === 'input' && item.settings.inputType === 'number'"
:key="item.id + item.settings.inputType"
v-model="item.value"
:required="item.settings.required"
:placeholder="item.settings.placeholder"
@ -573,6 +578,7 @@ export default {
/>
<el-input
v-else-if="item.type === 'textarea'"
:key="item.id + 'textarea'"
v-model="item.value"
type="textarea"
:required="item.settings.required"
@ -581,6 +587,7 @@ export default {
/>
<el-select
v-else-if="item.type === 'select'"
:key="item.id + 'select'"
v-model="item.value"
:required="item.settings.required"
:placeholder="item.settings.placeholder"
@ -598,6 +605,7 @@ export default {
</el-select>
<el-radio-group
v-else-if="item.type === 'radio'"
:key="item.id + 'radio'"
v-model="item.value"
:required="item.settings.required"
style="width: 100%"
@ -612,6 +620,7 @@ export default {
</el-radio-group>
<el-checkbox-group
v-else-if="item.type === 'checkbox'"
:key="item.id + 'checkbox'"
v-model="item.value"
:required="item.settings.required"
size="small"
@ -625,6 +634,7 @@ export default {
</el-checkbox-group>
<el-date-picker
v-else-if="item.type === 'date' && !item.settings.enableTime"
:key="item.id + 'date'"
v-model="item.value"
:required="item.settings.required"
type="date"
@ -634,6 +644,7 @@ export default {
/>
<el-date-picker
v-else-if="item.type === 'date' && item.settings.enableTime"
:key="item.id + 'dateEnableTime'"
v-model="item.value"
:required="item.settings.required"
type="datetime"
@ -643,6 +654,7 @@ export default {
/>
<el-date-picker
v-else-if="item.type === 'dateRange' && !item.settings.enableTime"
:key="item.id + 'dateRangeEnableTime'"
v-model="item.value"
:required="item.settings.required"
type="daterange"
@ -654,6 +666,7 @@ export default {
/>
<el-date-picker
v-else-if="item.type === 'dateRange' && item.settings.enableTime"
:key="item.id + 'datetimerangeRangeEnableTime'"
v-model="item.value"
:required="item.settings.required"
type="datetimerange"
@ -716,13 +729,28 @@ export default {
style="color: red"
>*</span>
</template>
<el-input
<el-select
v-model="selectedComponentItem.settings.rangeSeparator"
style="width: 100%"
required
>
<el-option
label="-"
value="-"
/>
<el-option
label="~"
value="~"
/>
</el-select>
<!-- <el-input
v-model.trim="selectedComponentItem.settings.rangeSeparator"
required
size="small"
maxlength="10"
maxlength="3"
show-word-limit
/>
/>-->
</el-form-item>
<el-form-item

View File

@ -127,7 +127,7 @@ export default {
}
).then(() => {
deleteForm(data.id).then((response) => {
if (this.displayFormData.id === data.id) {
if (this.displayFormData && this.displayFormData.id === data.id) {
this.displayFormData = undefined
}
listForm({}).then(res => {
@ -194,6 +194,11 @@ export default {
this.displayFormData = res.data
})
}
},
tabClick() {
if (this.activeName === 'my-tasks') {
this.$router.push('/data-filling/my-jobs')
}
}
}
}
@ -208,15 +213,14 @@ export default {
<el-tabs
v-model="activeName"
class="tab-panel"
@tab-click="tabClick"
>
<el-tab-pane
v-if="hasPermission(['my-data-filling:manage'])"
name="my-tasks"
>
<span slot="label">
<router-link to="/data-filling/my-jobs">
我的填报
</router-link>
我的填报
</span>
</el-tab-pane>
@ -382,6 +386,7 @@ export default {
class="m-dialog"
>
<el-container
v-if="showFolderCreateForm"
style="width: 100%"
direction="vertical"
>
@ -482,6 +487,13 @@ export default {
</template>
<style lang="scss" scoped>
.ms-aside-container {
height: calc(100vh - 56px);
padding: 0px;
min-width: 260px;
max-width: 460px;
}
.tab-panel {
height: 100%;
overflow-y: auto;

View File

@ -86,6 +86,7 @@ export default {
callback()
}
return {
loading: false,
requiredRule: { required: true, message: this.$t('commons.required'), trigger: ['blur', 'change'] },
duplicateRule: { validator: checkDuplicateNameValidator, trigger: 'blur' },
duplicateIndexRule: { validator: checkDuplicateIndexNameValidator, trigger: 'blur' },
@ -141,6 +142,7 @@ export default {
}
},
mounted() {
this.loading = true
this.formData = this.form
forEach(this.formData.forms, f => {
@ -149,34 +151,44 @@ export default {
f.settings.mapping.type = f.settings.mapping.typeOptions[0].value
}
})
const p1 = listDatasourceType()
const p2 = listDatasource()
const p3 = listForm({ nodeType: 'folder' })
listDatasourceType().then(res => {
this.allDatasourceTypes = res.data
})
Promise.all([p1, p2, p3]).then((val) => {
this.allDatasourceTypes = val[0].data
listDatasource().then(res => {
this.allDatasourceList = res.data
})
this.allDatasourceList = val[1].data
listForm({ nodeType: 'folder' }).then(res => {
this.folders = res.data || []
this.folders = val[2].data || []
if (this.formData.folder) {
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.formData.folder)
this.$refs.tree.setCheckedKeys([this.formData.folder])
})
}
}).finally(() => {
this.loading = false
})
},
methods: {
getTypeOptions(formOption) {
const _options = []
if (formOption.type !== 'date' && formOption.type !== 'dateRange' && formOption.settings.inputType !== 'number' && formOption.type !== 'textarea') {
if (formOption.type !== 'date' &&
formOption.type !== 'dateRange' &&
formOption.settings.inputType !== 'number' &&
formOption.type !== 'textarea' &&
formOption.type !== 'checkbox' &&
!(formOption.type === 'select' && formOption.settings.multiple)
) {
_options.push({ value: 'nvarchar', label: '字符串' })
}
if (formOption.type === 'textarea') {
if (formOption.type === 'checkbox' ||
formOption.type === 'select' && formOption.settings.multiple ||
formOption.type === 'textarea') {
_options.push({ value: 'text', label: '长文本' })
}
if (formOption.type === 'input' && formOption.settings.inputType === 'number') {
_options.push({ value: 'number', label: '整型数字' })
_options.push({ value: 'decimal', label: '小数数字' })
@ -240,6 +252,7 @@ export default {
return data.name.indexOf(value) !== -1
},
doSave() {
this.loading = true
this.$refs['mRightForm'].validate((valid) => {
if (valid) {
const data = {
@ -256,8 +269,11 @@ export default {
saveForm(data).then(res => {
this.closeSave()
this.$router.replace({ name: 'data-filling-form', query: { id: res.data }})
}).finally(() => {
this.loading = false
})
} else {
this.loading = false
return false
}
})
@ -267,7 +283,10 @@ export default {
</script>
<template>
<el-container class="DataFillingFormSave">
<el-container
v-loading="loading"
class="DataFillingFormSave"
>
<el-header class="de-header">
<div class="panel-info-area">
<span class="text16 margin-left12">
@ -392,6 +411,7 @@ export default {
</template>
<el-select
v-model="formData.datasource"
filterable
size="small"
style="width: 100%"
>

View File

@ -52,6 +52,24 @@ export default {
}
}
},
watch: {
currentKey: {
handler(newVal, oldVal) {
if (newVal !== oldVal) {
this.myTaskName = ''
this.finishedTaskName = ''
this.expiredTaskName = ''
}
if (newVal === 'finished') {
this.searchTableFinishedTaskData()
} else if (newVal === 'expired') {
this.searchTableExpiredTaskData()
} else {
this.searchTableMyTaskData()
}
}
}
},
mounted() {
this.currentKey = 'todo'
this.searchTableMyTaskData()
@ -62,12 +80,17 @@ export default {
},
changeKey(key) {
this.currentKey = key
if (key === 'finished') {
this.searchTableFinishedTaskData()
} else if (key === 'expired') {
this.searchTableExpiredTaskData()
},
entryKey(type) {
if (type === 'finished') {
this.$refs.search2.focus()
this.$refs.search2.blur()
} else if (type === 'expired') {
this.$refs.search3.focus()
this.$refs.search3.blur()
} else {
this.searchTableMyTaskData()
this.$refs.search1.focus()
this.$refs.search1.blur()
}
},
searchTableMyTaskData() {
@ -97,29 +120,29 @@ export default {
myTaskHandleSizeChange(pageSize) {
this.myTaskPaginationConfig.currentPage = 1
this.myTaskPaginationConfig.pageSize = pageSize
this.searchTableData()
this.searchTableMyTaskData()
},
myTaskHandleCurrentChange(currentPage) {
this.myTaskPaginationConfig.currentPage = currentPage
this.searchTableData()
this.searchTableMyTaskData()
},
finishedTaskHandleSizeChange(pageSize) {
this.finishedTaskPaginationConfig.currentPage = 1
this.finishedTaskPaginationConfig.pageSize = pageSize
this.searchTableData()
this.searchTableFinishedTaskData()
},
finishedTaskHandleCurrentChange(currentPage) {
this.finishedTaskPaginationConfig.currentPage = currentPage
this.searchTableData()
this.searchTableFinishedTaskData()
},
expiredTaskHandleSizeChange(pageSize) {
this.expiredTaskPaginationConfig.currentPage = 1
this.expiredTaskPaginationConfig.pageSize = pageSize
this.searchTableData()
this.searchTableExpiredTaskData()
},
expiredTaskHandleCurrentChange(currentPage) {
this.expiredTaskPaginationConfig.currentPage = currentPage
this.searchTableData()
this.searchTableExpiredTaskData()
},
getRestTime(time) {
if (!time) {
@ -246,7 +269,7 @@ export default {
obj[key] = undefined
}
} else {
obj[key] = value
obj[key] = value === null ? undefined : value
}
})
@ -282,6 +305,11 @@ export default {
} else {
this.searchTableMyTaskData()
}
},
tabClick() {
if (this.activeName === 'forms') {
this.$router.push('/data-filling/forms')
}
}
}
@ -298,6 +326,7 @@ export default {
<el-tabs
v-model="activeName"
class="tab-panel"
@tab-click="tabClick"
>
<el-tab-pane
name="my-tasks"
@ -324,9 +353,7 @@ export default {
<span
slot="label"
>
<router-link to="/data-filling/forms">
表单管理
</router-link>
表单管理
</span>
</el-tab-pane>
</el-tabs>
@ -344,7 +371,7 @@ export default {
:offset="16"
>
<el-input
ref="search"
ref="search1"
v-model="myTaskName"
:placeholder="$t('commons.search_by_name')"
prefix-icon="el-icon-search"
@ -352,7 +379,8 @@ export default {
size="small"
clearable
@blur="searchTableMyTaskData"
@clear="searchTableMyTaskData"
@clear="entryKey('todo')"
@keyup.enter.native="entryKey('todo')"
/>
</el-col>
</el-row>
@ -408,7 +436,7 @@ export default {
</el-table-column>
<el-table-column
key="id"
label="操作"
:label="$t('data_fill.form.operation')"
prop="id"
>
<template slot-scope="scope">
@ -436,15 +464,16 @@ export default {
:offset="16"
>
<el-input
ref="search"
ref="search2"
v-model="finishedTaskName"
:placeholder="$t('commons.search_by_name')"
prefix-icon="el-icon-search"
class="name-email-search"
size="small"
clearable
@blur="searchTableMyTaskData"
@clear="searchTableMyTaskData"
@blur="searchTableFinishedTaskData"
@clear="entryKey('finished')"
@keyup.enter.native="entryKey('finished')"
/>
</el-col>
</el-row>
@ -491,7 +520,7 @@ export default {
</el-table-column>
<el-table-column
key="id"
label="操作"
:label="$t('data_fill.form.operation')"
prop="id"
>
<template slot-scope="scope">
@ -525,15 +554,16 @@ export default {
:offset="16"
>
<el-input
ref="search"
ref="search3"
v-model="expiredTaskName"
:placeholder="$t('commons.search_by_name')"
prefix-icon="el-icon-search"
class="name-email-search"
size="small"
clearable
@blur="searchTableMyTaskData"
@clear="searchTableMyTaskData"
@blur="searchTableExpiredTaskData"
@clear="entryKey('expired')"
@keyup.enter.native="entryKey('expired')"
/>
</el-col>
</el-row>
@ -611,6 +641,12 @@ export default {
</template>
<style lang="scss" scoped>
.ms-aside-container {
height: calc(100vh - 56px);
padding: 0px;
min-width: 260px;
max-width: 460px;
}
.view-table {
background: rgba(255, 255, 255, 1);

View File

@ -122,11 +122,21 @@
</div>
</template>
<div class="check-item">
<el-checkbox
v-if="widget.name && ['textSelectWidget', 'textSelectGridWidget'].includes(widget.name)"
v-model="attrs.showEmpty"
>{{ $t('panel.show_empty') }}
</el-checkbox>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('time.passing_parameters')"
placement="top"
manual
v-model="visibleShowEmpty"
>
<el-checkbox
v-if="widget.name && ['textSelectWidget', 'textSelectGridWidget'].includes(widget.name)"
:disabled="attrs.enableParameters"
v-model="attrs.showEmpty"
><span @mouseenter="handlerVisibleShowEmpty" @mouseleave="handlerVisibleShowEmpty">{{ $t('panel.show_empty') }}</span>
</el-checkbox>
</el-tooltip>
</div>
<div class="check-item">
<el-checkbox
@ -184,13 +194,22 @@
</el-popover>
</div>
<div class="check-item">
<el-checkbox
v-if="showParams"
v-model="attrs.enableParameters"
@change="enableParametersChange"
><span>
{{ $t('panel.binding_parameters') }} </span>
</el-checkbox>
<el-tooltip
manual
v-model="visibleEnableParameters"
>
<template #content>
<span>{{ $t('time.not_supported') }}</span>
</template>
<el-checkbox
v-if="showParams"
:disabled="attrs.showEmpty"
v-model="attrs.enableParameters"
@change="enableParametersChange"
><span @mouseenter="handlerVisibleEnableParameters" @mouseleave="handlerVisibleEnableParameters">
{{ $t('panel.binding_parameters') }} </span>
</el-checkbox>
</el-tooltip>
<el-popover
placement="bottom-end"
:disabled="!attrs.enableParameters"
@ -320,6 +339,8 @@ export default {
{ label: this.$t('dataset.start_time'), name: 'start' },
{ label: this.$t('dataset.end_time'), name: 'end' }
],
visibleEnableParameters: false,
visibleShowEmpty: false,
showParams: false,
isRangeParamWidget: false,
attrs: null,
@ -422,6 +443,16 @@ export default {
}
},
methods: {
handlerVisibleEnableParameters() {
if (this.attrs.showEmpty) {
this.visibleEnableParameters = !this.visibleEnableParameters
}
},
handlerVisibleShowEmpty() {
if (this.attrs.enableParameters) {
this.visibleShowEmpty = !this.visibleShowEmpty
}
},
changeDynamicParams(val, name) {
const start = this.attrs.startParameters ? JSON.parse(JSON.stringify(this.attrs.startParameters)) : []
@ -520,7 +551,6 @@ export default {
margin-right: -4px;
margin-left: 6px;
border-radius: 4px;
color: #3370FF;
font-size: 14px;
font-weight: 400;
line-height: 22px;
@ -528,6 +558,7 @@ export default {
justify-content: center;
&:hover {
background: #3370FF1A;
color: #3370FF;
}
&.icon-icon-more::before {

View File

@ -55,6 +55,29 @@
>{{ $t('commons.required') }}</el-checkbox>
</div>
</el-col>
<el-dialog
:visible.sync="dialogVisible"
append-to-body
:show-close="false"
:close-on-press-escape="false"
:close-on-click-modal="false"
:before-close="sureRequired"
>
{{ $t('time.dropdown_display_must') }}
<div style="text-align: end;margin-top: 16px;">
<span slot="footer">
<el-button
size="mini"
@click="dialogVisible = false"
>{{ $t('commons.cancel') }}</el-button>
<el-button
type="primary"
size="mini"
@click="sureRequired"
>{{ $t('commons.confirm') }}</el-button>
</span>
</div>
</el-dialog>
</el-row>
</template>
@ -77,18 +100,22 @@ export default {
},
data() {
return {
targets: []
dialogVisible: false
}
},
computed: {
},
created() {
},
methods: {
sureRequired() {
this.element.options.attrs.required = false
this.dialogVisible = false
},
requiredChange(val) {
if (val === false && (this.element.style.showMode && this.element.style.showMode === 'radio' && !this.element.options.attrs.multiple)) {
this.dialogVisible = true
this.$nextTick(() => {
this.element.options.attrs.required = true
})
return
}
this.$emit('required-change', val)
},
getTableName(tableId) {

View File

@ -10,13 +10,15 @@
v-for="ele in intervalTypeList"
:key="ele.value"
:label="ele.value"
>{{ $t(`time.${ele.label}`) }}</el-radio
>
>{{ $t(`time.${ele.label}`) }}</el-radio>
</el-radio-group>
</div>
</div>
</div>
<div class="list-item" v-if="timeRange.intervalType !== 'none'">
<div
v-if="timeRange.intervalType !== 'none'"
class="list-item"
>
<div class="label">{{ $t(`time.${regularOrTrendsTitle}`) }}</div>
<div class="setting-content">
<div class="setting">
@ -33,7 +35,10 @@
{{ $t("time.relative_to_current") }}
</div>
<div class="setting-value select">
<el-select size="small" v-model="timeRange.relativeToCurrent">
<el-select
v-model="timeRange.relativeToCurrent"
size="small"
>
<el-option
v-for="item in relativeToCurrentList"
:key="item.value"
@ -43,7 +48,10 @@
</el-select>
</div>
</div>
<div class="setting" v-if="timeRange.relativeToCurrent === 'custom'">
<div
v-if="timeRange.relativeToCurrent === 'custom'"
class="setting"
>
<div class="setting-input">
<el-input-number
v-model="timeRange.timeNum"
@ -51,7 +59,10 @@
:min="0"
controls-position="right"
/>
<el-select size="small" v-model="timeRange.relativeToCurrentType">
<el-select
v-model="timeRange.relativeToCurrentType"
size="small"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -59,7 +70,10 @@
:value="item.value"
/>
</el-select>
<el-select size="small" v-model="timeRange.around">
<el-select
v-model="timeRange.around"
size="small"
>
<el-option
v-for="item in aroundList"
:key="item.value"
@ -82,7 +96,10 @@
:min="0"
controls-position="right"
/>
<el-select size="small" v-model="timeRange.relativeToCurrentType">
<el-select
v-model="timeRange.relativeToCurrentType"
size="small"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -90,7 +107,10 @@
:value="item.value"
/>
</el-select>
<el-select size="small" v-model="timeRange.around">
<el-select
v-model="timeRange.around"
size="small"
>
<el-option
v-for="item in aroundList"
:key="item.value"
@ -109,7 +129,10 @@
:min="0"
controls-position="right"
/>
<el-select size="small" v-model="timeRange.relativeToCurrentTypeRange">
<el-select
v-model="timeRange.relativeToCurrentTypeRange"
size="small"
>
<el-option
v-for="item in relativeToCurrentTypeList"
:key="item.value"
@ -117,7 +140,10 @@
:value="item.value"
/>
</el-select>
<el-select size="small" v-model="timeRange.aroundRange">
<el-select
v-model="timeRange.aroundRange"
size="small"
>
<el-option
v-for="item in aroundList"
:key="item.value"
@ -129,15 +155,21 @@
</div>
</template>
</div>
<div class="parameters" :class="dynamicTime && 'setting'">
<div class="setting-label" v-if="dynamicTime">
<div
class="parameters"
:class="dynamicTime && 'setting'"
>
<div
v-if="dynamicTime"
class="setting-label"
>
{{ $t("time.preview") }}
</div>
<div :class="dynamicTime ? 'setting-value' : 'w100'">
<el-date-picker
:disabled="timeRange.regularOrTrends !== 'fixed'"
v-model="timeRange.regularOrTrendsValue"
:key="timeInterval"
v-model="timeRange.regularOrTrendsValue"
:disabled="timeRange.regularOrTrends !== 'fixed'"
:type="timeInterval"
size="small"
:start-placeholder="$t('dataset.start_time')"
@ -161,6 +193,7 @@
<el-input-number
v-model="timeRange.maximumSingleQuery"
:min="1"
step-strictly
size="small"
controls-position="right"
/>
@ -168,103 +201,108 @@
</div>
</div>
<div class="popover-foot">
<de-btn secondary @click="closeFilter">{{ $t("chart.cancel") }} </de-btn>
<de-btn type="primary" @click="changeFilter"
>{{ $t("chart.confirm") }}
<de-btn
secondary
@click="closeFilter"
>{{ $t("chart.cancel") }} </de-btn>
<de-btn
type="primary"
@click="changeFilter"
>{{ $t("chart.confirm") }}
</de-btn>
</div>
</div>
</template>
<script>
import { getThisStart, getLastStart, getAround } from "./time-format-dayjs";
import { cloneDeep } from "lodash-es";
import { getThisStart, getLastStart, getAround } from './time-format-dayjs'
import { cloneDeep } from 'lodash-es'
const intervalTypeList = [
{
label: "nothing",
value: "none",
label: 'nothing',
value: 'none'
},
{
label: "starting_from",
value: "start",
label: 'starting_from',
value: 'start'
},
{
label: "end_at",
value: "end",
label: 'end_at',
value: 'end'
},
{
label: "time_interval",
value: "timeInterval",
},
];
label: 'time_interval',
value: 'timeInterval'
}
]
const aroundList = [
{
label: "ago",
value: "f",
label: 'ago',
value: 'f'
},
{
label: "after",
value: "b",
},
];
label: 'after',
value: 'b'
}
]
const relativeToCurrentTypeList = [
{
label: "year",
value: "year",
label: 'year',
value: 'year'
},
{
label: "month",
value: "month",
label: 'month',
value: 'month'
},
{
label: "day",
value: "day",
},
];
label: 'day',
value: 'day'
}
]
const relativeToCurrentList = [
{
label: "today",
value: "today",
label: 'today',
value: 'today'
},
{
label: "yesterday",
value: "yesterday",
label: 'yesterday',
value: 'yesterday'
},
{
label: "at_the_beginning_of_the_month",
value: "monthBeginning",
label: 'at_the_beginning_of_the_month',
value: 'monthBeginning'
},
{
label: "at_the_beginning_of_the_year",
value: "yearBeginning",
label: 'at_the_beginning_of_the_year',
value: 'yearBeginning'
},
{
label: "custom",
value: "custom",
},
];
label: 'custom',
value: 'custom'
}
]
const defaultObj = {
intervalType: "none",
intervalType: 'none',
dynamicWindow: false,
maximumSingleQuery: 0,
regularOrTrends: "fixed",
regularOrTrendsValue: "",
relativeToCurrent: "custom",
regularOrTrends: 'fixed',
regularOrTrendsValue: '',
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: "year",
around: "f",
relativeToCurrentType: 'year',
around: 'f',
timeNumRange: 0,
relativeToCurrentTypeRange: "year",
aroundRange: "f",
};
relativeToCurrentTypeRange: 'year',
aroundRange: 'f'
}
export default {
props: {
timeRangeData: {
type: Object,
defalut: () => defaultObj,
},
default: () => defaultObj
}
},
data() {
return {
@ -273,24 +311,20 @@ export default {
aroundList,
relativeToCurrentList,
timeRange: {
intervalType: "none",
intervalType: 'none',
dynamicWindow: false,
maximumSingleQuery: 0,
regularOrTrends: "fixed",
regularOrTrendsValue: "",
relativeToCurrent: "custom",
regularOrTrends: 'fixed',
regularOrTrendsValue: '',
relativeToCurrent: 'custom',
timeNum: 0,
relativeToCurrentType: "year",
around: "f",
relativeToCurrentType: 'year',
around: 'f',
timeNumRange: 0,
relativeToCurrentTypeRange: "year",
aroundRange: "f",
},
};
},
created() {
this.timeRange = cloneDeep(this.timeRangeData);
this.init();
relativeToCurrentTypeRange: 'year',
aroundRange: 'f'
}
}
},
computed: {
timeConfig() {
@ -299,41 +333,47 @@ export default {
relativeToCurrentType,
around,
intervalType,
relativeToCurrent,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
} = this.timeRange;
aroundRange
} = this.timeRange
return {
timeNum,
relativeToCurrentType,
relativeToCurrent,
around,
intervalType,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
};
aroundRange
}
},
regularOrTrendsTitle() {
return intervalTypeList.find(
(ele) => ele.value === this.timeRange.intervalType,
).label;
(ele) => ele.value === this.timeRange.intervalType
).label
},
dynamicTime() {
return this.timeRange.regularOrTrends !== "fixed";
return this.timeRange.regularOrTrends !== 'fixed'
},
timeInterval() {
return this.timeRange.intervalType === "timeInterval"
? "daterange"
: "date";
},
return this.timeRange.intervalType === 'timeInterval'
? 'daterange'
: 'date'
}
},
watch: {
timeConfig: {
handler() {
this.init();
this.init()
},
deep: true,
},
deep: true
}
},
created() {
this.timeRange = cloneDeep(this.timeRangeData)
this.init()
},
methods: {
init() {
@ -347,87 +387,111 @@ export default {
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
regularOrTrends,
} = this.timeRange;
if (regularOrTrends === "fixed") {
if (intervalType === "timeInterval") {
regularOrTrends
} = this.timeRange
if (regularOrTrends === 'fixed') {
if (intervalType === 'timeInterval') {
if (
Array.isArray(regularOrTrendsValue) &&
!!regularOrTrendsValue.length
)
return;
) { return }
this.timeRange.regularOrTrendsValue = [
getAround(relativeToCurrentType, "add", 0),
getAround(relativeToCurrentType, "add", 1),
];
return;
getAround(relativeToCurrentType, 'add', 0),
getAround(relativeToCurrentType, 'add', 1)
]
return
}
if (!Array.isArray(regularOrTrendsValue) && !!regularOrTrendsValue)
return;
this.timeRange.regularOrTrendsValue = new Date();
return;
if (!Array.isArray(regularOrTrendsValue) && !!regularOrTrendsValue) { return }
this.timeRange.regularOrTrendsValue = new Date()
return
}
if (intervalType === "timeInterval") {
if (intervalType === 'timeInterval') {
const startTime = getAround(
relativeToCurrentType,
around === "f" ? "subtract" : "add",
timeNum,
);
around === 'f' ? 'subtract' : 'add',
timeNum
)
const endTime = getAround(
relativeToCurrentTypeRange,
aroundRange === "f" ? "subtract" : "add",
timeNumRange,
);
this.timeRange.regularOrTrendsValue = [startTime, endTime];
return;
aroundRange === 'f' ? 'subtract' : 'add',
timeNumRange
)
this.timeRange.regularOrTrendsValue = [startTime, endTime]
return
}
if (relativeToCurrent === "custom") {
if (relativeToCurrent === 'custom') {
this.timeRange.regularOrTrendsValue = getAround(
relativeToCurrentType,
around === "f" ? "subtract" : "add",
timeNum,
);
around === 'f' ? 'subtract' : 'add',
timeNum
)
} else {
switch (relativeToCurrent) {
case "thisYear":
this.timeRange.regularOrTrendsValue = getThisStart("year");
break;
case "lastYear":
this.timeRange.regularOrTrendsValue = getLastStart("year");
break;
case "thisMonth":
this.timeRange.regularOrTrendsValue = getThisStart("month");
break;
case "lastMonth":
this.timeRange.regularOrTrendsValue = getLastStart("month");
break;
case "today":
this.timeRange.regularOrTrendsValue = getThisStart("day");
break;
case "yesterday":
this.timeRange.regularOrTrendsValue = getLastStart("day");
break;
case "monthBeginning":
this.timeRange.regularOrTrendsValue = getThisStart("month");
break;
case "yearBeginning":
this.timeRange.regularOrTrendsValue = getThisStart("year");
break;
case 'thisYear':
this.timeRange.regularOrTrendsValue = getThisStart('year')
break
case 'lastYear':
this.timeRange.regularOrTrendsValue = getLastStart('year')
break
case 'thisMonth':
this.timeRange.regularOrTrendsValue = getThisStart('month')
break
case 'lastMonth':
this.timeRange.regularOrTrendsValue = getLastStart('month')
break
case 'today':
this.timeRange.regularOrTrendsValue = getThisStart('day')
break
case 'yesterday':
this.timeRange.regularOrTrendsValue = getLastStart('day')
break
case 'monthBeginning':
this.timeRange.regularOrTrendsValue = getThisStart('month')
break
case 'yearBeginning':
this.timeRange.regularOrTrendsValue = getThisStart('year')
break
default:
break;
break
}
}
},
closeFilter() {
this.timeRange = cloneDeep(defaultObj);
this.$emit("changeData", null);
this.timeRange = cloneDeep(this.timeRangeData)
this.$emit('changeData', null)
},
changeFilter() {
this.$emit("changeData", cloneDeep(this.timeRange));
},
},
};
const {
timeNum,
relativeToCurrentType,
around,
intervalType,
timeNumRange,
regularOrTrends,
relativeToCurrentTypeRange,
aroundRange
} = this.timeRange
if (intervalType === 'timeInterval' && regularOrTrends === 'dynamic') {
const startTime = getAround(
relativeToCurrentType,
around === 'f' ? 'subtract' : 'add',
timeNum
)
const endTime = getAround(
relativeToCurrentTypeRange,
aroundRange === 'f' ? 'subtract' : 'add',
timeNumRange
)
if (+endTime < +startTime) {
this.$message.error(this.$t('time.end_time_start_time'))
return
}
}
this.$emit('changeData', cloneDeep(this.timeRange))
}
}
}
</script>
<style lang="less">
.set-time-filtering-range {

View File

@ -26,6 +26,69 @@
/>
</el-select>
</el-input>
<el-dropdown
trigger="click"
@command="sortTypeChange"
>
<div class="insert-filter filter-icon-span">
<svg-icon
v-show="curSortType.includes('asc')"
class="opt-icon"
icon-class="dv-sort-asc"
/>
<svg-icon
v-show="curSortType.includes('desc')"
class="opt-icon"
icon-class="dv-sort-desc"
/>
</div>
<template #dropdown>
<el-dropdown-menu style="width: 160px">
<el-dropdown-item
class="sort-type-normal"
:class="{ 'sort-type-checked': curSortType === 'time_asc' }"
:command="beforeClickItem('time_asc')"
>
<span>按创建时间升序</span>
<i
style="margin-left: 4px; line-height: 32px"
class="el-icon-check"
/>
</el-dropdown-item>
<el-dropdown-item
class="sort-type-normal"
:class="{ 'sort-type-checked': curSortType === 'time_desc' }"
:command="beforeClickItem('time_desc')"
>
<span>按创建时间降序</span><i
style="margin-left: 4px; line-height: 32px"
class="el-icon-check"
/>
</el-dropdown-item>
<el-divider class="custom-driver" />
<el-dropdown-item
class="sort-type-normal"
:class="{ 'sort-type-checked': curSortType === 'name_asc' }"
:command="beforeClickItem('name_asc')"
>
<span>按照名称升序</span><i
style="margin-left: 4px; line-height: 32px"
class="el-icon-check"
/>
</el-dropdown-item>
<el-dropdown-item
class="sort-type-normal"
:class="{ 'sort-type-checked': curSortType === 'name_desc' }"
:command="beforeClickItem('name_desc')"
>
<span>按照名称降序</span><i
style="margin-left: 4px; line-height: 32px"
class="el-icon-check"
/>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
</el-row>
<el-row class="de-tree">
@ -459,7 +522,8 @@ import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel'
import TreeSelector from '@/components/treeSelector'
import { queryAuthModel } from '@/api/authModel/authModel'
import msgCfm from '@/components/msgCfm/index'
import { updateCacheTree } from '@/components/canvas/utils/utils'
import { deepCopy, updateCacheTree } from '@/components/canvas/utils/utils'
import treeSort from '@/utils/treeSortUtils'
export default {
name: 'PanelList',
@ -467,6 +531,9 @@ export default {
mixins: [msgCfm],
data() {
return {
originResourceTree: [],
curSortType: 'time_desc',
localSortParams: null,
lastActiveDefaultPanelId: null, //
responseSource: 'panelQuery',
defaultExpansion: false,
@ -614,6 +681,7 @@ export default {
beforeDestroy() {
},
mounted() {
this.loadInit()
this.clearCanvas()
this.initCache()
const routerParam = this.$router.currentRoute.params
@ -637,6 +705,24 @@ export default {
}
},
methods: {
loadInit() {
const historyLocalSortType = localStorage.getItem('TreeSort-panel')
if (historyLocalSortType) {
this.localSortParams = { sortType: historyLocalSortType }
} else {
this.localSortParams = { sortType: this.curSortType }
}
},
beforeClickItem(type) {
return {
sortType: type
}
},
sortTypeChange(params) {
this.tData = treeSort(this.originResourceTree, this.curSortType, params.sortType)
this.curSortType = params.sortType
localStorage.setItem('TreeSort-panel', this.curSortType)
},
activeLastNode() {
this.$nextTick(() => {
document.querySelector('.is-current').firstChild.click()
@ -674,9 +760,10 @@ export default {
updateCacheTree(this.editPanel.optType,
panelInfo.panelType === 'system' ? 'panel-default-tree' : 'panel-main-tree', panelInfo,
panelInfo.panelType === 'system' ? this.defaultData : this.tData)
if (this.editPanel.optType === 'rename' && panelInfo.id === this.$store.state.panel.panelInfo.id) {
this.$store.state.panel.panelInfo.name = panelInfo.name
if (this.editPanel.optType === 'rename' && panelInfo.id === this.$store.panel.panelInfo.id) {
this.$store.panel.panelInfo.name = panelInfo.name
}
this.originResourceTree = deepCopy(this.tData)
//
if (
panelInfo &&
@ -852,7 +939,7 @@ export default {
},
delete(data) {
const title = data.source ? 'commons.cancel_this_dashboard':(data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard')
const title = data.source ? 'commons.cancel_this_dashboard' : (data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard')
const params = {
title: title,
type: 'danger',
@ -865,6 +952,7 @@ export default {
})
this.clearCanvas()
updateCacheTree('delete', 'panel-main-tree', data.id, this.tData)
this.originResourceTree = deepCopy(this.tData)
this.defaultTree(false)
})
}
@ -898,12 +986,14 @@ export default {
const modelInfo = localStorage.getItem('panel-main-tree')
const userCache = modelInfo && cache
if (userCache) {
this.tData = JSON.parse(modelInfo)
this.originResourceTree = JSON.parse(modelInfo)
this.sortTypeChange(this.localSortParams)
}
groupTree(this.groupForm, !userCache).then((res) => {
localStorage.setItem('panel-main-tree', JSON.stringify(res.data || []))
if (!userCache) {
this.tData = res.data || []
this.originResourceTree = res.data || []
this.sortTypeChange(this.localSortParams)
}
if (this.responseSource === 'appApply') {
this.fromAppActive()
@ -1122,6 +1212,7 @@ export default {
this.moveInfo['optType'] = 'move'
panelMove(this.moveInfo).then((response) => {
updateCacheTree('move', 'panel-main-tree', response.data, this.tData)
this.originResourceTree = deepCopy(this.tData)
this.closeMoveGroup()
})
},
@ -1185,6 +1276,7 @@ export default {
}
.main-area-input {
width: calc(100% - 40px);
::v-deep.el-input-group__append {
width: 70px;
background: transparent;
@ -1249,4 +1341,69 @@ export default {
.link-dialog ::v-deep .el-dialog__headerbtn {
z-index: 1;
}
.insert-filter {
display: inline-block;
font-weight: 400 !important;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer;
color: var(--TextPrimary, #1f2329);
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: 0;
margin: 0;
transition: 0.1s;
border-radius: 3px;
&:active {
color: #000;
border-color: #3a8ee6;
background-color: red;
outline: 0;
}
&:hover {
background-color: rgba(31, 35, 41, 0.1);
color: #3a8ee6;
}
}
.filter-icon-span {
border: 1px solid #dcdfe6;
width: 32px;
height: 32px;
border-radius: 4px;
padding: 7px;
margin-left: 8px;
}
.menu-outer-dv_popper {
width: 140px;
margin-top: -2px !important;
.ed-icon {
border-radius: 4px;
}
}
.sort-type-normal {
display: flex;
i {
display: none;
}
}
.sort-type-checked {
color: #3370ff;
i {
display: block;
}
}
.custom-driver {
margin: 12px 0
}
</style>

View File

@ -242,6 +242,7 @@ export default {
//
this.canvasStyleData.chartInfo.chartCommonStyle.backgroundColorSelect = true
this.canvasStyleData.panel.backgroundType = 'color'
this.canvasStyleData.panel['alpha'] = 100
if (this.overallSettingForm.panel.themeColor === 'light') {
this.canvasStyleData.panel.color = deepCopy(LIGHT_THEME_PANEL_BACKGROUND)
this.canvasStyleData.chartInfo.chartCommonStyle.color = deepCopy(LIGHT_THEME_COMPONENT_BACKGROUND)

View File

@ -37,7 +37,10 @@
"home": {
"tab1": "My Favorites",
"tab2": "Recent",
"tab3": "Share With Me"
"tab3": "Share With Me",
"empty_tips_1": "No favorite dashboards yet!",
"empty_tips_2": "No browsing history yet!",
"empty_tips_3": "No dashboards shared with me yet!"
},
"dir": {
"searchHistory": "Search History",

View File

@ -37,7 +37,10 @@
"home": {
"tab1": "我的收藏",
"tab2": "最近浏览",
"tab3": "分享给我"
"tab3": "分享给我",
"empty_tips_1": "暂无收藏的仪表板!",
"empty_tips_2": "暂无浏览记录!",
"empty_tips_3": "暂无分享给我的仪表板!"
},
"dir": {
"searchPlaceholder": "请输入仪表板名称",

View File

@ -38,7 +38,10 @@
"home": {
"tab1": "我的收藏",
"tab2": "最近瀏覽",
"tab3": "分享給我"
"tab3": "分享給我",
"empty_tips_1": "暫無收藏的儀表板!",
"empty_tips_2": "暫無瀏覽記錄!",
"empty_tips_3": "暫無分享給我的儀表板!"
},
"dir": {
"searchPlaceholder": "請輸入儀表板名稱",

View File

@ -67,7 +67,7 @@
navigateFlag: false,
pulling: false,
refreshIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5QTFRFcHBw3Nzct7e39vb2ycnJioqK7e3tpqam29vb////D8oK7wAAAAp0Uk5T////////////ALLMLM8AAABxSURBVHja7JVBDoAgDASrjqj//7CJBi90iyYeOHTPMwmFZrHjYyyFYYUy1bwUZqtJIYVxhf1a6u0R7iUvWsCcrEtwJHp8MwMdvh2amHduiZD3rpWId9+BgPd7Cc2LIkPyqvlQvKxKBJ//Qwq/CacAAwDUv0a0YuKhzgAAAABJRU5ErkJggg==",
emptyTextList: ['暂无收藏仪表板', '暂无浏览记录', '暂无分享给我的']
emptyTextList: [this.$t('home.empty_tips_1'), this.$t('home.empty_tips_2'), this.$t('home.empty_tips_3')]
}
},
computed: {

View File

@ -2,6 +2,9 @@
<div style="width: 100%;">
<el-col>
<el-form ref="labelForm" :model="labelForm" label-width="80px" size="mini">
<el-divider content-position="left"><span style="font-size: 12px">主轴标签</span></el-divider>
<el-form-item :label="$t('chart.show')" class="form-item">
<el-checkbox v-model="labelForm.show" @change="changeLabelAttr">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
@ -44,39 +47,52 @@
/>
</el-select>
</el-form-item>
<!-- <el-form-item :label="$t('chart.label')" class="form-item">
<el-select v-model="values" :placeholder="$t('commons.please_select')" multiple collapse-tags
@change="changeFields">
<el-option-group
v-for="group in fieldOptions"
:key="group.label"
:label="group.label"
>
<el-option
v-for="item in group.options"
:key="item.id"
:label="item.name"
:value="item.id"
:disabled="item.disabled">
</el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item class="form-item">
<span slot="label">
<span class="span-box">
<span>{{ $t('chart.content_formatter') }}</span>
<el-tooltip class="item" effect="dark" placement="bottom">
<div slot="content">
{{ $t('plugin_view_chartmix.tooltip_format_tip') }}
</div>
<i class="el-icon-info" style="cursor: pointer;"/>
</el-tooltip>
</span>
</span>
<el-input v-model="labelForm.labelTemplate" type="textarea" :placeholder="defaultPlaceholder"
:autosize="{ minRows: 4, maxRows: 4}" @blur="changeLabelAttr"/>
</el-form-item>-->
</div>
<el-divider content-position="left"><span style="font-size: 12px">副轴标签</span></el-divider>
<el-form-item :label="$t('chart.show')" class="form-item">
<el-checkbox v-model="labelForm.subShow" @change="changeLabelAttr">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="labelForm.subShow">
<el-form-item :label="$t('chart.text_fontsize')" class="form-item">
<el-select v-model="labelForm.subFontSize" :placeholder="$t('chart.text_fontsize')" size="mini"
@change="changeLabelAttr">
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value"/>
</el-select>
</el-form-item>
<el-form-item :label="$t('chart.text_color')" class="form-item">
<el-color-picker v-model="labelForm.subColor" class="color-picker-style" :predefine="predefineColors"
@change="changeLabelAttr"/>
</el-form-item>
<el-form-item
class="form-item"
>
<template #label>
{{ $t('chart.label_position') }}
<el-tooltip
effect="dark"
content="仅对柱状图生效"
>
<i
class="el-icon-info"
style="cursor: pointer;"
/>
</el-tooltip>
</template>
<el-select
v-model="labelForm.subPosition"
:placeholder="$t('chart.label_position')"
@change="changeLabelAttr"
>
<el-option
v-for="option in labelPositionV"
:key="option.value"
:label="option.name"
:value="option.value"
/>
</el-select>
</el-form-item>
</div>
</el-form>
@ -85,7 +101,7 @@
</template>
<script>
import {COLOR_PANEL, DEFAULT_LABEL, getDefaultTemplate} from '@/utils/map'
import {COLOR_PANEL, DEFAULT_LABEL, getDefaultTemplate} from '../../utils/map'
export default {
name: 'LabelSelector',
@ -195,6 +211,13 @@ export default {
if (!this.labelForm.labelLine) {
this.labelForm.labelLine = JSON.parse(JSON.stringify(DEFAULT_LABEL.labelLine))
}
if (this.labelForm.subShow === undefined) {
this.labelForm.subShow = DEFAULT_LABEL.subShow
this.labelForm.subPosition = DEFAULT_LABEL.subPosition
this.labelForm.subColor = DEFAULT_LABEL.subColor
this.labelForm.subFontSize = DEFAULT_LABEL.subFontSize
}
if (!customAttr.label.initialized) {
this.changeLabelAttr();
}
@ -270,6 +293,7 @@ export default {
.form-item ::v-deep .el-checkbox__label {
font-size: 12px;
}
.form-item ::v-deep .el-radio__label {
font-size: 12px;
}

View File

@ -23,7 +23,7 @@
<el-dropdown-item>
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="sort">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-sort" />
<span>{{ $t('chart.sort') }}</span>
<span class="summary-span-item">({{ $t('chart.'+item.sort) }})</span>
@ -41,7 +41,7 @@
<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">
<span>
<span class="inline-menu-text">
<i class="el-icon-c-scale-to-original" />
<span>{{ $t('chart.dateStyle') }}</span>
<span class="summary-span-item">({{ $t('chart.'+item.dateStyle) }})</span>
@ -61,7 +61,7 @@
<el-dropdown-item v-show="item.deType === 1">
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="datePattern">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-timer" />
<span>{{ $t('chart.datePattern') }}</span>
<span class="summary-span-item">({{ $t('chart.'+item.datePattern) }})</span>
@ -251,4 +251,9 @@ export default {
margin-left: 4px;
color: #878d9f;
}
.inline-menu-text {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@ -78,7 +78,7 @@
@command="sort"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-sort"/>
<span>{{ $t('chart.sort') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.sort) }})</span>
@ -107,7 +107,7 @@
@command="dateStyle"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-c-scale-to-original"/>
<span>{{ $t('chart.dateStyle') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.dateStyle) }})</span>
@ -149,7 +149,7 @@
@command="datePattern"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-timer"/>
<span>{{ $t('chart.datePattern') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.datePattern) }})</span>
@ -420,4 +420,9 @@ span {
margin-left: 4px;
color: #878d9f;
}
.inline-menu-text {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

View File

@ -33,7 +33,7 @@
<el-dropdown-item v-show="chart.type ==='chart-mix'">
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="switchChartType">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-s-data"/>
<span>{{ $t('chart.chart_type') }}</span>
</span>
@ -49,7 +49,7 @@
<el-dropdown-item v-show="chart.type !== 'table-info'" :divided="chart.type === 'chart-mix'">
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="summary">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-notebook-2"/>
<span>{{ $t('chart.summary') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.summary) }})</span>
@ -83,7 +83,7 @@
@command="quickCalc"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-s-grid"/>
<span>{{ $t('chart.quick_calc') }}</span>
<span class="summary-span-item">({{
@ -114,7 +114,7 @@
@command="sort"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-sort"/>
<span>{{ $t('chart.sort') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.sort) }})</span>
@ -391,6 +391,11 @@ span {
margin-left: 4px;
color: #878d9f;
}
.inline-menu-text {
display: flex;
flex-direction: row;
align-items: center;
}
.summary-span {
margin-left: 4px;

View File

@ -33,7 +33,7 @@
<el-dropdown-item v-show="chart.type ==='chart-mix'">
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="switchChartType">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-s-data"/>
<span>{{ $t('chart.chart_type') }}</span>
</span>
@ -49,7 +49,7 @@
<el-dropdown-item :divided="chart.type === 'chart-mix'">
<el-dropdown placement="right-start" size="mini" style="width: 100%" @command="summary">
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-notebook-2"/>
<span>{{ $t('chart.summary') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.summary) }})</span>
@ -83,7 +83,7 @@
@command="quickCalc"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-s-grid"/>
<span>{{ $t('chart.quick_calc') }}</span>
<span class="summary-span-item">({{
@ -114,7 +114,7 @@
@command="sort"
>
<span class="el-dropdown-link inner-dropdown-menu">
<span>
<span class="inline-menu-text">
<i class="el-icon-sort"/>
<span>{{ $t('chart.sort') }}</span>
<span class="summary-span-item">({{ $t('chart.' + item.sort) }})</span>
@ -391,6 +391,11 @@ span {
margin-left: 4px;
color: #878d9f;
}
.inline-menu-text {
display: flex;
flex-direction: row;
align-items: center;
}
.summary-span {
margin-left: 4px;

View File

@ -60,6 +60,10 @@ export const DEFAULT_LABEL = {
position: 'middle',
color: '#000000',
fontSize: '10',
subShow: true,
subPosition: 'middle',
subColor: '#000000',
subFontSize: '10',
formatter: '{c}',
gaugeFormatter: '{value}',
labelLine: {

View File

@ -39,7 +39,8 @@ import {
DEFAULT_XAXIS_STYLE,
DEFAULT_YAXIS_STYLE,
transAxisPosition,
getLineDash, DEFAULT_COLOR_CASE, formatterItem, DEFAULT_YAXIS_EXT_STYLE
getLineDash, DEFAULT_COLOR_CASE, formatterItem, DEFAULT_YAXIS_EXT_STYLE,
DEFAULT_LABEL
} from '../../../utils/map';
import ChartTitleUpdate from '../../../components/views/ChartTitleUpdate';
import {map, filter, join, flatten, cloneDeep} from 'lodash-es';
@ -279,7 +280,9 @@ export default {
let colors = undefined;
let alpha = DEFAULT_COLOR_CASE.alpha;
let labelSetting = undefined;
let labelPosition = 'middle';
let labelPosition = DEFAULT_LABEL.position;
let subLabelSetting = undefined;
let subLabelPosition = DEFAULT_LABEL.subPosition;
if (this.chart.customAttr) {
customAttr = JSON.parse(this.chart.customAttr);
if (customAttr) {
@ -296,6 +299,14 @@ export default {
},
} : false
labelPosition = customAttr.label.position;
subLabelSetting = customAttr.label.subShow ? {
style: {
fill: customAttr.label.subColor,
fontSize: parseInt(customAttr.label.subFontSize),
},
} : false
subLabelPosition = customAttr.label.subPosition;
}
}
}
@ -348,7 +359,7 @@ export default {
}
) : [];
const yExtData = [this.getYExtData(flatten(yExtChartData), labelSetting, labelPosition, yaxisExtList, colors, gradient, alpha, xAxis, yAxisExt, yaxisCount)];
const yExtData = [this.getYExtData(flatten(yExtChartData), subLabelSetting, subLabelPosition, yaxisExtList, colors, gradient, alpha, xAxis, yAxisExt, yaxisCount)];
const params = {
tooltip: false,
@ -364,7 +375,7 @@ export default {
if (customAttr.tooltip) {
params.tooltip = customAttr.tooltip.show ? {
showTitle: false,
showTitle: true,
showMarkers: false,
shared: true,
// node tooltipedge tooltip

View File

@ -2,7 +2,7 @@ version: '2.1'
services:
mysql:
image: registry.cn-qingdao.aliyuncs.com/dataease/mysql:8.1.0
image: registry.cn-qingdao.aliyuncs.com/dataease/mysql:8.3.0
container_name: mysql
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u${DE_MYSQL_USER}", "-p${DE_MYSQL_PASSWORD}"]

View File

@ -17,7 +17,7 @@ import java.util.regex.Pattern;
@Setter
public class DatasourceRequest {
private final String REG_WITH_SQL_FRAGMENT = "((?i)WITH[\\s\\S]+(?i)AS?\\s*\\([\\s\\S]+\\))\\s*(?i)SELECT";
private Pattern WITH_SQL_FRAGMENT = Pattern.compile(REG_WITH_SQL_FRAGMENT);
private Pattern WITH_SQL_FRAGMENT = Pattern.compile(REG_WITH_SQL_FRAGMENT);
protected String query;
@ -43,6 +43,7 @@ public class DatasourceRequest {
private boolean totalPageFlag;
private List<TableFieldWithValue> tableFieldWithValues;
private boolean lowerCaseTaleNames;
@Getter
@Setter

View File

@ -66,4 +66,9 @@ public class DefaultExtDDLProvider extends ExtDDLProvider {
public String whereSql(String tableName, List<TableField> searchFields) {
return null;
}
@Override
public String getLowerCaseTaleNames() {
return null;
}
}

View File

@ -32,4 +32,6 @@ public abstract class ExtDDLProvider {
public abstract String checkUniqueValueSql(String tableName, DatasourceRequest.TableFieldWithValue field, DatasourceRequest.TableFieldWithValue pk);
public abstract String whereSql(String tableName, List<TableField> searchFields);
public abstract String getLowerCaseTaleNames();
}