diff --git a/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/entity/CoreDatasource.java b/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/entity/CoreDatasource.java index a141d413bf..ddf6d34292 100644 --- a/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/entity/CoreDatasource.java +++ b/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/entity/CoreDatasource.java @@ -7,11 +7,11 @@ import java.io.Serializable; /** *

- * + * 数据源表 *

* * @author fit2cloud - * @since 2023-09-26 + * @since 2024-07-09 */ @TableName("core_datasource") public class CoreDatasource implements Serializable { @@ -89,6 +89,11 @@ public class CoreDatasource implements Serializable { */ private String taskStatus; + /** + * 开启数据填报 + */ + private Boolean enableDataFill; + public Long getId() { return id; } @@ -201,6 +206,14 @@ public class CoreDatasource implements Serializable { this.taskStatus = taskStatus; } + public Boolean getEnableDataFill() { + return enableDataFill; + } + + public void setEnableDataFill(Boolean enableDataFill) { + this.enableDataFill = enableDataFill; + } + @Override public String toString() { return "CoreDatasource{" + @@ -218,6 +231,7 @@ public class CoreDatasource implements Serializable { ", status = " + status + ", qrtzInstance = " + qrtzInstance + ", taskStatus = " + taskStatus + + ", enableDataFill = " + enableDataFill + "}"; } } diff --git a/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/mapper/CoreDatasourceMapper.java b/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/mapper/CoreDatasourceMapper.java index d6e7170bd1..a27bc9ad36 100644 --- a/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/mapper/CoreDatasourceMapper.java +++ b/core/core-backend/src/main/java/io/dataease/datasource/dao/auto/mapper/CoreDatasourceMapper.java @@ -6,11 +6,11 @@ import org.apache.ibatis.annotations.Mapper; /** *

- * Mapper 接口 + * 数据源表 Mapper 接口 *

* * @author fit2cloud - * @since 2023-09-26 + * @since 2024-07-09 */ @Mapper public interface CoreDatasourceMapper extends BaseMapper { diff --git a/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java b/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java index a6ff053f04..b5acae0241 100644 --- a/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java +++ b/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java @@ -26,10 +26,10 @@ import org.apache.calcite.adapter.jdbc.JdbcSchema; import org.apache.calcite.jdbc.CalciteConnection; import org.apache.calcite.schema.Schema; import org.apache.calcite.schema.SchemaPlus; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; import java.io.File; import java.io.IOException; @@ -54,6 +54,7 @@ public class CalciteProvider extends Provider { private final String FILE_PATH = "/opt/dataease2.0/drivers"; private final String CUSTOM_PATH = "/opt/dataease2.0/custom-drivers/"; private static String split = "DE"; + @Resource private CommonThreadPool commonThreadPool; @@ -214,7 +215,9 @@ public class CalciteProvider extends Provider { List datasetTableFields = new ArrayList<>(); DatasourceSchemaDTO datasourceSchemaDTO = datasourceRequest.getDsList().entrySet().iterator().next().getValue(); datasourceRequest.setDatasource(datasourceSchemaDTO); + DatasourceConfiguration datasourceConfiguration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), DatasourceConfiguration.class); + String table = datasourceRequest.getTable(); if (StringUtils.isEmpty(table)) { ResultSet resultSet = null; @@ -371,11 +374,20 @@ public class CalciteProvider extends Provider { // schema ResultSet resultSet = null; try (ConnectionObj con = getConnection(datasourceRequest.getDatasource()); - Statement statement = getStatement(con.getConnection(), datasourceConfiguration.getQueryTimeout())) { + PreparedStatement statement = getPreparedStatement(con.getConnection(), datasourceConfiguration.getQueryTimeout(), datasourceRequest.getQuery())) { if (DatasourceConfiguration.DatasourceType.valueOf(value.getType()) == DatasourceConfiguration.DatasourceType.oracle) { statement.executeUpdate("ALTER SESSION SET CURRENT_SCHEMA = " + datasourceConfiguration.getSchema()); } - resultSet = statement.executeQuery(datasourceRequest.getQuery()); + + if (CollectionUtils.isNotEmpty(datasourceRequest.getTableFieldWithValues())) { + LogUtil.info("execWithPreparedStatement sql: " + datasourceRequest.getQuery()); + for (int i = 0; i < datasourceRequest.getTableFieldWithValues().size(); i++) { + statement.setObject(i + 1, datasourceRequest.getTableFieldWithValues().get(i).getValue(), datasourceRequest.getTableFieldWithValues().get(i).getType()); + LogUtil.info("execWithPreparedStatement param[" + (i + 1) + "]: " + datasourceRequest.getTableFieldWithValues().get(i).getValue()); + } + } + + resultSet = statement.executeQuery(); fieldList = getField(resultSet, datasourceRequest); dataList = getData(resultSet, datasourceRequest); } catch (SQLException e) { @@ -397,6 +409,88 @@ public class CalciteProvider extends Provider { return map; } + @Override + public void exec(DatasourceRequest datasourceRequest) throws DEException { + DatasourceSchemaDTO value = datasourceRequest.getDsList().entrySet().iterator().next().getValue(); + datasourceRequest.setDatasource(value); + + DatasourceConfiguration datasourceConfiguration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), DatasourceConfiguration.class); + + // schema + ResultSet resultSet = null; + try (ConnectionObj con = getConnection(datasourceRequest.getDatasource()); + PreparedStatement statement = getPreparedStatement(con.getConnection(), datasourceConfiguration.getQueryTimeout(), datasourceRequest.getQuery())) { + if (DatasourceConfiguration.DatasourceType.valueOf(value.getType()) == DatasourceConfiguration.DatasourceType.oracle) { + statement.executeUpdate("ALTER SESSION SET CURRENT_SCHEMA = " + datasourceConfiguration.getSchema()); + } + + if (CollectionUtils.isNotEmpty(datasourceRequest.getTableFieldWithValues())) { + LogUtil.info("execWithPreparedStatement sql: " + datasourceRequest.getQuery()); + for (int i = 0; i < datasourceRequest.getTableFieldWithValues().size(); i++) { + statement.setObject(i + 1, datasourceRequest.getTableFieldWithValues().get(i).getValue(), datasourceRequest.getTableFieldWithValues().get(i).getType()); + LogUtil.info("execWithPreparedStatement param[" + (i + 1) + "]: " + datasourceRequest.getTableFieldWithValues().get(i).getValue()); + } + } + + statement.execute(); + + } catch (SQLException e) { + DEException.throwException("SQL ERROR: " + e.getMessage()); + } catch (Exception e) { + DEException.throwException("Data source connection exception: " + e.getMessage()); + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public int executeUpdate(DatasourceRequest datasourceRequest) throws DEException { + DatasourceSchemaDTO value = datasourceRequest.getDsList().entrySet().iterator().next().getValue(); + datasourceRequest.setDatasource(value); + + DatasourceConfiguration datasourceConfiguration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), DatasourceConfiguration.class); + + // schema + ResultSet resultSet = null; + try (ConnectionObj con = getConnection(datasourceRequest.getDatasource()); + PreparedStatement statement = getPreparedStatement(con.getConnection(), datasourceConfiguration.getQueryTimeout(), datasourceRequest.getQuery())) { + if (DatasourceConfiguration.DatasourceType.valueOf(value.getType()) == DatasourceConfiguration.DatasourceType.oracle) { + statement.executeUpdate("ALTER SESSION SET CURRENT_SCHEMA = " + datasourceConfiguration.getSchema()); + } + + if (CollectionUtils.isNotEmpty(datasourceRequest.getTableFieldWithValues())) { + LogUtil.info("execWithPreparedStatement sql: " + datasourceRequest.getQuery()); + for (int i = 0; i < datasourceRequest.getTableFieldWithValues().size(); i++) { + statement.setObject(i + 1, datasourceRequest.getTableFieldWithValues().get(i).getValue(), datasourceRequest.getTableFieldWithValues().get(i).getType()); + LogUtil.info("execWithPreparedStatement param[" + (i + 1) + "]: " + datasourceRequest.getTableFieldWithValues().get(i).getValue()); + } + } + + return statement.executeUpdate(); + + } catch (SQLException e) { + DEException.throwException("SQL ERROR: " + e.getMessage()); + } catch (Exception e) { + DEException.throwException("Data source connection exception: " + e.getMessage()); + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + + return 0; + } + private List getField(ResultSet rs, DatasourceRequest datasourceRequest) throws Exception { List fieldList = new ArrayList<>(); ResultSetMetaData metaData = rs.getMetaData(); @@ -588,14 +682,14 @@ public class CalciteProvider extends Provider { String[] databasePrams = matcher.group(3).split("\\?"); database = databasePrams[0]; } - sql = String.format("SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'", database, datasourceRequest.getTable()); + sql = String.format("SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,IF(COLUMN_KEY='PRI',1,0) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'", database, datasourceRequest.getTable()); break; case oracle: configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), Oracle.class); if (StringUtils.isEmpty(configuration.getSchema())) { DEException.throwException(Translator.get("i18n_schema_is_empty")); } - sql = String.format("SELECT a.COLUMN_NAME , a.DATA_TYPE , b.COMMENTS FROM all_tab_columns a LEFT JOIN all_col_comments b ON a.owner = b.owner AND a.table_name = b.table_name AND a.column_name = b.column_name WHERE a.owner = '%s' AND a.table_name = '%s' ORDER BY a.table_name, a.column_id", configuration.getSchema(), datasourceRequest.getTable()); + sql = String.format("SELECT a.COLUMN_NAME , a.DATA_TYPE , b.COMMENTS ,0 FROM all_tab_columns a LEFT JOIN all_col_comments b ON a.owner = b.owner AND a.table_name = b.table_name AND a.column_name = b.column_name WHERE a.owner = '%s' AND a.table_name = '%s' ORDER BY a.table_name, a.column_id", configuration.getSchema(), datasourceRequest.getTable()); break; case db2: configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), Db2.class); @@ -611,7 +705,7 @@ public class CalciteProvider extends Provider { } sql = String.format("SELECT \n" + - " c.name ,t.name ,ep.value \n" + + " c.name ,t.name ,ep.value, 0 \n" + "FROM \n" + " sys.columns AS c\n" + "LEFT JOIN sys.extended_properties AS ep ON c.object_id = ep.major_id AND c.column_id = ep.minor_id\n" + @@ -627,7 +721,8 @@ public class CalciteProvider extends Provider { sql = String.format("SELECT\n" + " a.attname AS ColumnName,\n" + " t.typname,\n" + - " b.description AS ColumnDescription\n" + + " b.description AS ColumnDescription,\n" + + " 0\n" + "FROM\n" + " pg_class c\n" + " JOIN pg_attribute a ON a.attrelid = c.oid\n" + @@ -646,7 +741,8 @@ public class CalciteProvider extends Provider { sql = String.format("SELECT\n" + " a.attname AS ColumnName,\n" + " t.typname,\n" + - " b.description AS ColumnDescription\n" + + " b.description AS ColumnDescription,\n" + + " 0\n" + "FROM\n" + " pg_class c\n" + " JOIN pg_attribute a ON a.attrelid = c.oid\n" + @@ -675,7 +771,8 @@ public class CalciteProvider extends Provider { sql = String.format(" SELECT\n" + " name,\n" + " type,\n" + - " comment\n" + + " comment,\n" + + " 0\n" + "FROM\n" + " system.columns\n" + "WHERE\n" + @@ -702,6 +799,10 @@ public class CalciteProvider extends Provider { tableField.setDeExtractType(deType); tableField.setDeType(deType); tableField.setName(resultSet.getString(3)); + try { + tableField.setPrimary(resultSet.getInt(4) > 0); + } catch (Exception e) { + } return tableField; } @@ -1092,6 +1193,32 @@ public class CalciteProvider extends Provider { } } + public Statement getStatement(Connection connection, int queryTimeout) { + if (connection == null) { + DEException.throwException("Failed to get connection!"); + } + Statement stat = null; + try { + stat = connection.createStatement(); + stat.setQueryTimeout(queryTimeout); + } catch (Exception e) { + DEException.throwException(e.getMessage()); + } + return stat; + } + + public PreparedStatement getPreparedStatement(Connection connection, int queryTimeout, String sql) throws Exception { + if (connection == null) { + throw new Exception("Failed to get connection!"); + } + PreparedStatement stat = connection.prepareStatement(sql); + try { + stat.setQueryTimeout(queryTimeout); + } catch (Exception e) { + } + return stat; + } + protected boolean isDefaultClassLoader(String customDriver) { return StringUtils.isEmpty(customDriver) || customDriver.equalsIgnoreCase("default"); } diff --git a/core/core-backend/src/main/java/io/dataease/datasource/server/DatasourceServer.java b/core/core-backend/src/main/java/io/dataease/datasource/server/DatasourceServer.java index 8db4b316a6..e57cc64e7c 100644 --- a/core/core-backend/src/main/java/io/dataease/datasource/server/DatasourceServer.java +++ b/core/core-backend/src/main/java/io/dataease/datasource/server/DatasourceServer.java @@ -1,5 +1,6 @@ package io.dataease.datasource.server; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -356,7 +357,8 @@ public class DatasourceServer implements DatasourceApi { List toCreateTables = new ArrayList<>(); List toDeleteTables = new ArrayList<>(); if (dataSourceDTO.getType().equals(DatasourceConfiguration.DatasourceType.API.name())) { - List sourceTables = ApiUtils.getTables(sourceTableRequest).stream().map(DatasetTableDTO::getTableName).collect(Collectors.toList()); + requestDatasource.setEnableDataFill(null); + List sourceTables = ApiUtils.getTables(sourceTableRequest).stream().map(DatasetTableDTO::getTableName).toList(); List datasetTableDTOS = ApiUtils.getTables(datasourceRequest); List tables = datasetTableDTOS.stream().map(DatasetTableDTO::getTableName).collect(Collectors.toList()); checkName(datasetTableDTOS.stream().map(DatasetTableDTO::getName).collect(Collectors.toList())); @@ -410,6 +412,7 @@ public class DatasourceServer implements DatasourceApi { dataSourceManage.checkName(dataSourceDTO); dataSourceManage.innerEdit(requestDatasource); } else if (dataSourceDTO.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name())) { + requestDatasource.setEnableDataFill(null); List sourceTables = ExcelUtils.getTables(sourceTableRequest).stream().map(DatasetTableDTO::getTableName).collect(Collectors.toList()); List tables = ExcelUtils.getTables(datasourceRequest).stream().map(DatasetTableDTO::getTableName).collect(Collectors.toList()); if (dataSourceDTO.getEditType() == 0) { @@ -439,6 +442,9 @@ public class DatasourceServer implements DatasourceApi { dataSourceManage.innerEdit(requestDatasource); } } else { + if (!LicenseUtil.licenseValid()) { + requestDatasource.setEnableDataFill(null); + } checkParams(dataSourceDTO.getConfiguration()); dataSourceManage.checkName(dataSourceDTO); dataSourceManage.innerEdit(requestDatasource); @@ -515,12 +521,39 @@ public class DatasourceServer implements DatasourceApi { return getDatasourceDTOById(datasourceId, false); } + @Override + public DatasourceDTO innerGet(Long datasourceId) throws DEException { + return getDatasourceDTOById(datasourceId, false); + } + + @Override + public List innerList(List ids) throws DEException { + List list = new ArrayList<>(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (ids != null) { + if (ids.isEmpty()) { + return list; + } else { + queryWrapper.in(CoreDatasource::getId, ids); + } + } + List dsList = datasourceMapper.selectList(queryWrapper); + for (CoreDatasource datasource : dsList) { + list.add(convertCoreDatasource(datasource.getId(), false, datasource)); + } + return list; + } + private DatasourceDTO getDatasourceDTOById(Long datasourceId, boolean hidePw) throws DEException { - DatasourceDTO datasourceDTO = new DatasourceDTO(); CoreDatasource datasource = datasourceMapper.selectById(datasourceId); if (datasource == null) { DEException.throwException("不存在的数据源!"); } + return convertCoreDatasource(datasourceId, hidePw, datasource); + } + + private DatasourceDTO convertCoreDatasource(Long datasourceId, boolean hidePw, CoreDatasource datasource) { + DatasourceDTO datasourceDTO = new DatasourceDTO(); BeanUtils.copyBean(datasourceDTO, datasource); if (datasourceDTO.getType().equalsIgnoreCase(DatasourceConfiguration.DatasourceType.API.toString())) { diff --git a/core/core-backend/src/main/java/io/dataease/job/schedule/DeDataFillingTaskExecutor.java b/core/core-backend/src/main/java/io/dataease/job/schedule/DeDataFillingTaskExecutor.java new file mode 100644 index 0000000000..b2f999244e --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/job/schedule/DeDataFillingTaskExecutor.java @@ -0,0 +1,111 @@ +package io.dataease.job.schedule; + +import io.dataease.commons.utils.CronUtils; +import io.dataease.license.config.XpackInteract; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.quartz.JobDataMap; +import org.quartz.JobKey; +import org.quartz.TriggerKey; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.Map; + +@Component("deDataFillingTaskExecutor") +public class DeDataFillingTaskExecutor { + + protected static final String IS_TEMP_TASK = "isTempTask"; + protected static final String IS_RETRY_TASK = "isRetryTask"; + + private static final String JOB_GROUP = "REPORT_TASK"; + private static final String RETRY_JOB_GROUP = "RETRY_REPORT_TASK"; + private static final String TEMP_JOB_GROUP = "TEMP_REPORT_TASK"; + + @Resource + private ScheduleManager scheduleManager; + + @XpackInteract(value = "dataFillingTaskExecutor", replace = true) + public boolean execute(Map taskData) { + return false; + } + + @XpackInteract(value = "dataFillingTaskExecutor", replace = true) + public void init() { + } + + public void addOrUpdateTask(Long taskId, String cron, Long startTime, Long endTime) { + if (CronUtils.taskExpire(endTime)) { + return; + } + String key = taskId.toString(); + JobKey jobKey = new JobKey(key, JOB_GROUP); + TriggerKey triggerKey = new TriggerKey(key, JOB_GROUP); + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("taskId", taskId); + jobDataMap.put(IS_TEMP_TASK, false); + Date end = null; + if (ObjectUtils.isNotEmpty(endTime)) end = new Date(endTime); + scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, DeXpackDataFillingScheduleJob.class, cron, startTime == null ? null : new Date(startTime), end, jobDataMap); + } + + public void addRetryTask(Long taskId, Integer retryLimit, Integer retryInterval) { + long saltTime = 3000L; + long interval = retryInterval == null ? 5L : retryInterval; + long intervalMill = interval * 60000L; + long now = System.currentTimeMillis(); + String cron = "0 */" + interval + " * * * ?"; + long endTime = (retryLimit + 1) * intervalMill + now - saltTime; + String key = taskId.toString(); + if (CronUtils.taskExpire(endTime)) { + return; + } + JobKey jobKey = new JobKey(key, RETRY_JOB_GROUP); + TriggerKey triggerKey = new TriggerKey(key, RETRY_JOB_GROUP); + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("taskId", taskId); + jobDataMap.put(IS_RETRY_TASK, true); + Date end = null; + if (ObjectUtils.isNotEmpty(endTime)) end = new Date(endTime); + scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, DeXpackDataFillingScheduleJob.class, cron, new Date(now), end, jobDataMap); + } + + public boolean fireNow(Long taskId) throws Exception { + String key = taskId.toString(); + JobKey jobKey = new JobKey(key, JOB_GROUP); + if (scheduleManager.exist(jobKey)) { + scheduleManager.fireNow(jobKey); + return true; + } + return false; + } + + public void addTempTask(Long taskId, Long startTime) { + String key = taskId.toString(); + JobKey jobKey = new JobKey(key, TEMP_JOB_GROUP); + TriggerKey triggerKey = new TriggerKey(key, TEMP_JOB_GROUP); + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put(IS_TEMP_TASK, true); + String cron = CronUtils.tempCron(); + jobDataMap.put("taskId", taskId); + scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, DeXpackDataFillingScheduleJob.class, cron, new Date(startTime), null, jobDataMap); + } + + public void removeTask(Long taskId, boolean isTemp) { + String key = taskId.toString(); + JobKey jobKey = new JobKey(key, isTemp ? TEMP_JOB_GROUP : JOB_GROUP); + TriggerKey triggerKey = new TriggerKey(key, isTemp ? TEMP_JOB_GROUP : JOB_GROUP); + scheduleManager.removeJob(jobKey, triggerKey); + } + + public void removeRetryTask(Long taskId) { + String key = taskId.toString(); + JobKey jobKey = new JobKey(key, RETRY_JOB_GROUP); + TriggerKey triggerKey = new TriggerKey(key, RETRY_JOB_GROUP); + scheduleManager.removeJob(jobKey, triggerKey); + } + + public void clearRetryTask() throws Exception { + scheduleManager.clearByGroup(RETRY_JOB_GROUP); + } +} diff --git a/core/core-backend/src/main/java/io/dataease/job/schedule/DeXpackDataFillingScheduleJob.java b/core/core-backend/src/main/java/io/dataease/job/schedule/DeXpackDataFillingScheduleJob.java new file mode 100644 index 0000000000..bc5e69f15b --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/job/schedule/DeXpackDataFillingScheduleJob.java @@ -0,0 +1,27 @@ +package io.dataease.job.schedule; + +import io.dataease.license.utils.LicenseUtil; +import io.dataease.utils.CommonBeanFactory; +import org.quartz.*; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +@Component +public class DeXpackDataFillingScheduleJob implements Job { + + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + Trigger trigger = jobExecutionContext.getTrigger(); + JobKey jobKey = trigger.getJobKey(); + JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); + DeDataFillingTaskExecutor deTaskExecutor = CommonBeanFactory.getBean(DeDataFillingTaskExecutor.class); + assert deTaskExecutor != null; + LicenseUtil.validate(); + boolean taskLoaded = deTaskExecutor.execute(jobDataMap); + if (!taskLoaded) { + Objects.requireNonNull(CommonBeanFactory.getBean(ScheduleManager.class)).removeJob(jobKey, trigger.getKey()); + } + } +} diff --git a/core/core-backend/src/main/java/io/dataease/listener/XpackTaskStarter.java b/core/core-backend/src/main/java/io/dataease/listener/XpackTaskStarter.java index 0154a29f6f..eb83895a7c 100644 --- a/core/core-backend/src/main/java/io/dataease/listener/XpackTaskStarter.java +++ b/core/core-backend/src/main/java/io/dataease/listener/XpackTaskStarter.java @@ -1,5 +1,6 @@ package io.dataease.listener; +import io.dataease.job.schedule.DeDataFillingTaskExecutor; import io.dataease.job.schedule.DeTaskExecutor; import io.dataease.license.utils.LicenseUtil; import io.dataease.utils.LogUtil; @@ -16,6 +17,9 @@ public class XpackTaskStarter implements ApplicationRunner { @Resource private DeTaskExecutor deTaskExecutor; + @Resource + private DeDataFillingTaskExecutor deDataFillingTaskExecutor; + @Override public void run(ApplicationArguments args) { try { @@ -24,5 +28,11 @@ public class XpackTaskStarter implements ApplicationRunner { } catch (Exception e) { LogUtil.error(e.getMessage(), e.getCause()); } + try { + LicenseUtil.validate(); + deDataFillingTaskExecutor.init(); + } catch (Exception e) { + LogUtil.error(e.getMessage(), e.getCause()); + } } } diff --git a/core/core-backend/src/main/java/io/dataease/menu/manage/MenuManage.java b/core/core-backend/src/main/java/io/dataease/menu/manage/MenuManage.java index 3319213d2f..56c0b8c20a 100644 --- a/core/core-backend/src/main/java/io/dataease/menu/manage/MenuManage.java +++ b/core/core-backend/src/main/java/io/dataease/menu/manage/MenuManage.java @@ -100,6 +100,8 @@ public class MenuManage { || coreMenu.getId().equals(28L) || coreMenu.getId().equals(35L) || coreMenu.getId().equals(40L) - || coreMenu.getId().equals(50L); + || coreMenu.getId().equals(50L) + || coreMenu.getId().equals(60L) + || coreMenu.getId().equals(61L); } } diff --git a/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql b/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql index e081ee1bb5..e47e7c76d2 100644 --- a/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql +++ b/core/core-backend/src/main/resources/db/desktop/V2.10__ddl.sql @@ -1,3 +1,6 @@ BEGIN; INSERT INTO `core_sys_startup_job` VALUES ('chartFilterDynamic', 'chartFilterDynamic', 'ready'); COMMIT; + +alter table `core_datasource` + add `enable_data_fill` tinyint default 0 null comment '启用数据填报功能'; diff --git a/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql index e081ee1bb5..e47e7c76d2 100644 --- a/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql +++ b/core/core-backend/src/main/resources/db/migration/V2.10__ddl.sql @@ -1,3 +1,6 @@ BEGIN; INSERT INTO `core_sys_startup_job` VALUES ('chartFilterDynamic', 'chartFilterDynamic', 'ready'); COMMIT; + +alter table `core_datasource` + add `enable_data_fill` tinyint default 0 null comment '启用数据填报功能'; diff --git a/core/core-backend/src/main/resources/i18n/core_zh_CN.properties b/core/core-backend/src/main/resources/i18n/core_zh_CN.properties index d7b38b465d..92383858c6 100644 --- a/core/core-backend/src/main/resources/i18n/core_zh_CN.properties +++ b/core/core-backend/src/main/resources/i18n/core_zh_CN.properties @@ -12,6 +12,7 @@ i18n_menu.template-setting=\u6A21\u677F\u7BA1\u7406 i18n_menu.view=\u6570\u636E\u5C55\u793A i18n_menu.data=\u6570\u636E\u51C6\u5907 i18n_menu.panel=\u4EEA\u8868\u677F +i18n_menu.data-filling-manage=\u6570\u636E\u586B\u62A5 i18n_menu.screen=\u6570\u636E\u5927\u5C4F i18n_menu.dataset=\u6570\u636E\u96C6 i18n_menu.datasource=\u6570\u636E\u6E90 @@ -43,7 +44,7 @@ i18n_table_duplicate=\u76F8\u540C\u8282\u70B9\u9700\u91CD\u65B0\u62D6\u5165\u624 i18n_no_column_permission=\u6CA1\u6709\u5217\u6743\u9650 i18n_fetch_error=SQL\u6267\u884C\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8868\u3001\u5B57\u6BB5\u3001\u5173\u8054\u5173\u7CFB\u7B49\u4FE1\u606F\u662F\u5426\u6B63\u786E\u5E76\u91CD\u65B0\u7F16\u8F91\u3002 i18n_no_datasource_permission=\u65E0\u6570\u636E\u6E90\u8BBF\u95EE\u6743\u9650 -i18n_no_dataset_permission=\u65e0\u6570\u636e\u96c6\u8bbf\u95ee\u6743\u9650 +i18n_no_dataset_permission=\u65E0\u6570\u636E\u96C6\u8BBF\u95EE\u6743\u9650 i18n_not_full=\u5F53\u524D\u6570\u636E\u6E90\u4E0D\u652F\u6301\u5168\u8FDE\u63A5 i18n_field_circular_ref=\u5B57\u6BB5\u5B58\u5728\u5FAA\u73AF\u5F15\u7528 diff --git a/core/core-frontend/src/api/data-filling.ts b/core/core-frontend/src/api/data-filling.ts new file mode 100644 index 0000000000..ff017ecf1d --- /dev/null +++ b/core/core-frontend/src/api/data-filling.ts @@ -0,0 +1,226 @@ +import request from '@/config/axios' +import dayjs from 'dayjs' + +export function formatDate(value, dateType) { + if (!value) { + return value + } + switch (dateType) { + case 'year': + return dayjs(value).format('YYYY') + case 'month': + case 'monthrange': + return dayjs(value).format('YYYY-MM') + case 'datetime': + case 'datetimerange': + return dayjs(value).format('YYYY-MM-DD HH:mm:ss') + default: + return dayjs(value).format('YYYY-MM-DD') + } +} +export interface ColumnItem { + props: string + label: string + date: boolean + dateType?: string + type: string + multiple: boolean + rangeIndex?: number + disabled?: boolean +} +export interface DataFillingOrFolder { + name: string + action?: string + id?: number | string + pid?: number | string + nodeType: 'folder' | 'data-filling' + union?: Array<{}> + allFields?: Array<{}> +} + +export interface Tree { + name: string + value?: string | number + id: string | number + nodeType: string + createBy?: string + level: number + leaf?: boolean + pid: string | number + type?: string + createTime: number + children?: Tree[] + request: any +} + +export interface DfFormSetting { + id?: string + name?: string + pid?: string + datasource?: string + tableName?: string + forms: Array + createIndex: boolean + tableIndexes: Array + + creator?: string + updater?: string + createTime?: number + updateTime?: number + weight?: number +} + +export interface DfFormItem { + type: string + typeName: string + icon: string + order?: number + value?: any + id?: string + settings: FormItemSetting + old?: boolean + removed?: boolean +} + +export interface FormItemSetting { + name?: string + placeholder?: string + required?: boolean + unique?: boolean + inputType?: string + optionSourceType?: 1 | 2 + optionDatasource?: number + optionTable?: string + optionColumn?: string + optionOrder?: string + multiple?: boolean + dateType?: 'date' | 'daterange' + rangeSeparator?: string + startPlaceholder?: string + endPlaceholder?: string + options?: Array + mapping: { + columnName?: string + columnName1?: string + columnName2?: string + type?: string + } +} + +export interface FormItemSettingOptions { + name: string + value: string +} + +export interface SimpleDatasource { + id: string + pid: string + name: string + type: string + typeAlias: string + status: string + enableDataFill: boolean +} + +export const listDataFillingForms = async (data): Promise => { + return request + .post({ url: '/data-filling/tree', data: { ...data, ...{ busiFlag: 'data-filling' } } }) + .then(res => { + return res?.data + }) +} + +export const createFolder = (data = {}): Promise => { + return request + .post({ url: '/data-filling/save', data: { ...data, nodeType: 'folder' } }) + .then(res => { + return res?.data + }) +} +export const save = (data = {}): Promise => { + return request.post({ url: '/data-filling/save', data }).then(res => { + return res?.data + }) +} + +export const move = (data = {}): Promise => { + return request.post({ url: '/data-filling/move', data }).then(res => { + return res?.data + }) +} + +export const reName = (data = {}): Promise => { + return request.post({ url: '/data-filling/rename', data }).then(res => { + return res?.data + }) +} +export const listDatasourceList = (): Promise> => { + return request.get({ url: '/data-filling/datasource/list' }).then(res => { + return res?.data + }) +} + +export const getDataFilling = async (id: string): Promise => { + return request.get({ url: `/data-filling/get/${id}` }).then(res => { + return res?.data + }) +} + +export const deleteById = (id: string): Promise => { + return request.get({ url: '/data-filling/delete/' + id }) +} + +export const deleteRowData = (formId: string, id: number): Promise => { + return request.get({ url: `/data-filling/form/${formId}/delete/${id}` }) +} + +export const batchDeleteRowData = (formId: string, data: Array): Promise => { + return request.post({ url: `/data-filling/form/${formId}/batch-delete`, data }) +} + +export const getTableColumnData = ( + optionDatasource, + optionTable, + optionColumn, + optionOrder +): Promise => { + return request.post({ + url: `/data-filling/form/${optionDatasource}/options`, + data: { + optionTable: optionTable, + optionColumn: optionColumn, + optionOrder: optionOrder + } + }) +} + +export const searchTable = (id, data): Promise => { + return request.post({ + url: '/data-filling/form/' + id + '/tableData', + data + }) +} + +export const saveFormRowData = (formId, data): Promise => { + return request + .post({ + url: '/data-filling/form/' + formId + '/rowData/save', + data + }) + .then(res => { + return res?.data + }) +} + +export const saveTask = (data): Promise => { + return request.post({ + url: `/data-filling/task/save`, + data + }) +} + +export const getTaskInfo = (taskId): Promise => { + return request.get({ + url: `/data-filling/task/info/${taskId}` + }) +} diff --git a/core/core-frontend/src/assets/svg/icon_file-doc_colorful.svg b/core/core-frontend/src/assets/svg/icon_file-doc_colorful.svg new file mode 100644 index 0000000000..7371ef72ab --- /dev/null +++ b/core/core-frontend/src/assets/svg/icon_file-doc_colorful.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/core/core-frontend/src/assets/svg/icon_multi-line_outlined.svg b/core/core-frontend/src/assets/svg/icon_multi-line_outlined.svg new file mode 100644 index 0000000000..24c4b1cc2c --- /dev/null +++ b/core/core-frontend/src/assets/svg/icon_multi-line_outlined.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/core/core-frontend/src/assets/svg/icon_radio_outlined.svg b/core/core-frontend/src/assets/svg/icon_radio_outlined.svg new file mode 100644 index 0000000000..2206cec10f --- /dev/null +++ b/core/core-frontend/src/assets/svg/icon_radio_outlined.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/core/core-frontend/src/assets/svg/icon_single-line_outlined.svg b/core/core-frontend/src/assets/svg/icon_single-line_outlined.svg new file mode 100644 index 0000000000..5cd8e7b53d --- /dev/null +++ b/core/core-frontend/src/assets/svg/icon_single-line_outlined.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/core/core-frontend/src/assets/svg/icon_todo_outlined.svg b/core/core-frontend/src/assets/svg/icon_todo_outlined.svg new file mode 100644 index 0000000000..633b9b1ece --- /dev/null +++ b/core/core-frontend/src/assets/svg/icon_todo_outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue b/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue index 293382d1e1..a8de71f1c7 100644 --- a/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue +++ b/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue @@ -33,6 +33,18 @@ const userDrawer = ref(false) const init = () => { userDrawer.value = true } +const cleanrInnerValue = (index: number) => { + const field = componentList.value[index]?.field + if (!field) { + return + } + myRefs.value[index]?.clear() + for (let i = 0; i < state.conditions.length; i++) { + if (state.conditions[i].field === field) { + state.conditions[i].value = [] + } + } +} const clearInnerTag = (index?: number) => { if (isNaN(index)) { for (let i = 0; i < componentList.value.length; i++) { @@ -74,6 +86,7 @@ const filterChange = (value, field, operator) => { if (!exits && value?.length) { state.conditions.push({ field, value, operator }) } + treeFilterChange(value, field, operator) } const reset = () => { clearFilter() @@ -82,14 +95,22 @@ const reset = () => { const close = () => { userDrawer.value = false } -const emits = defineEmits(['trigger-filter']) +const emits = defineEmits(['trigger-filter', 'tree-filter-change']) const trigger = () => { emits('trigger-filter', state.conditions) } +const treeFilterChange = (value, field, operator) => { + emits('tree-filter-change', { + value, + field, + operator + }) +} defineExpose({ init, clearFilter, - close + close, + cleanrInnerValue }) diff --git a/core/core-frontend/src/components/icon-custom/src/Icon.vue b/core/core-frontend/src/components/icon-custom/src/Icon.vue index cd5c87b9e4..7d967ce2b3 100644 --- a/core/core-frontend/src/components/icon-custom/src/Icon.vue +++ b/core/core-frontend/src/components/icon-custom/src/Icon.vue @@ -661,6 +661,11 @@ import wizard_quick_start from '@/assets/svg/wizard_quick_start.svg' import wordCloudDark from '@/assets/svg/word-cloud-dark.svg' import wordCloudOrigin from '@/assets/svg/word-cloud-origin.svg' import wordCloud from '@/assets/svg/word-cloud.svg' +import icon_multi_line_outlined from '@/assets/svg/icon_multi-line_outlined.svg' +import icon_radio_outlined from '@/assets/svg/icon_radio_outlined.svg' +import icon_single_line_outlined from '@/assets/svg/icon_single-line_outlined.svg' +import icon_todo_outlined from '@/assets/svg/icon_todo_outlined.svg' +import icon_file_doc_colorful from '@/assets/svg/icon_file-doc_colorful.svg' const iconMap = { '401': _401, '403': _403, @@ -1062,6 +1067,10 @@ const iconMap = { 'icon_right-association': icon_rightAssociation, icon_right_outlined: icon_right_outlined, icon_scroll_filled: icon_scroll_filled, + icon_radio_outlined: icon_radio_outlined, + icon_todo_outlined: icon_todo_outlined, + 'icon_single-line_outlined': icon_single_line_outlined, + 'icon_multi-line_outlined': icon_multi_line_outlined, 'icon_search-outline_outlined': icon_searchOutline_outlined, icon_search: icon_search, 'icon_share-label_filled': icon_shareLabel_filled, @@ -1320,7 +1329,8 @@ const iconMap = { wizard_quick_start: wizard_quick_start, 'word-cloud-dark': wordCloudDark, 'word-cloud-origin': wordCloudOrigin, - 'word-cloud': wordCloud + 'word-cloud': wordCloud, + 'icon_file-doc_colorful': icon_file_doc_colorful } const props = defineProps({ diff --git a/core/core-frontend/src/custom-component/v-query/DynamicTimeRangeFiltering.vue b/core/core-frontend/src/custom-component/v-query/DynamicTimeRangeFiltering.vue index 4a8630f3e7..971f86f52f 100644 --- a/core/core-frontend/src/custom-component/v-query/DynamicTimeRangeFiltering.vue +++ b/core/core-frontend/src/custom-component/v-query/DynamicTimeRangeFiltering.vue @@ -3,11 +3,12 @@ import { toRefs, PropType, onBeforeMount, watch, computed } from 'vue' import { Calendar } from '@element-plus/icons-vue' import { type DatePickType } from 'element-plus-secondary' import type { ManipulateType } from 'dayjs' -import { getAround } from './time-format-dayjs' +import { getAround, getCustomRange } from './time-format-dayjs' interface SelectConfig { regularOrTrends: string regularOrTrendsValue: [Date, Date] intervalType: string + relativeToCurrentRange: string timeNum: number relativeToCurrentType: ManipulateType around: string @@ -27,6 +28,7 @@ const props = defineProps({ regularOrTrends: 'fixed', timeNum: 0, intervalType: 'none', + relativeToCurrentRange: 'custom', relativeToCurrentType: 'year', around: 'f', timeGranularity: 'date', @@ -50,6 +52,7 @@ const timeConfig = computed(() => { timeNum, relativeToCurrentType, around, + relativeToCurrentRange, intervalType, regularOrTrends, timeGranularity, @@ -62,6 +65,7 @@ const timeConfig = computed(() => { relativeToCurrentType, around, intervalType, + relativeToCurrentRange, regularOrTrends, timeGranularity, timeNumRange, @@ -87,10 +91,13 @@ watch( ) const init = () => { + console.log('relativeToCurrentRange') + const { timeNum, relativeToCurrentType, around, + relativeToCurrentRange, regularOrTrends, timeNumRange, relativeToCurrentTypeRange, @@ -117,6 +124,11 @@ const init = () => { timeNumRange ) + if (!!relativeToCurrentRange && relativeToCurrentRange !== 'custom') { + config.value.regularOrTrendsValue = getCustomRange(relativeToCurrentRange) + return + } + config.value.regularOrTrendsValue = [startTime, endTime] } diff --git a/core/core-frontend/src/custom-component/v-query/QueryConditionConfiguration.vue b/core/core-frontend/src/custom-component/v-query/QueryConditionConfiguration.vue index e012f070c5..b5ab99edc2 100644 --- a/core/core-frontend/src/custom-component/v-query/QueryConditionConfiguration.vue +++ b/core/core-frontend/src/custom-component/v-query/QueryConditionConfiguration.vue @@ -576,16 +576,21 @@ const isInRange = (ele, startWindowTime, timeStamp) => { if (intervalType === 'timeInterval') { const startTime = regularOrTrends === 'fixed' - ? regularOrTrendsValue[0] + ? new Date( + dayjs(new Date(regularOrTrendsValue[0])).startOf(noTime).format('YYYY/MM/DD HH:mm:ss') + ) : getAround(relativeToCurrentType, around === 'f' ? 'subtract' : 'add', timeNum) const endTime = regularOrTrends === 'fixed' - ? regularOrTrendsValue[1] + ? new Date( + dayjs(new Date(regularOrTrendsValue[1])).endOf(noTime).format('YYYY/MM/DD HH:mm:ss') + ) : getAround( relativeToCurrentTypeRange, aroundRange === 'f' ? 'subtract' : 'add', timeNumRange ) + return ( startWindowTime < +new Date(startTime) - 1000 || timeStamp > +new Date(endTime) || @@ -760,7 +765,7 @@ const validate = () => { 'end-config' ) : new Date(ele.defaultValue[1]) - if (!relativeToCurrentRange || relativeToCurrentRange === 'custom') { + if (!!relativeToCurrentRange && relativeToCurrentRange !== 'custom') { ;[startTime, endTime] = getCustomRange(relativeToCurrentRange) } if (+startTime > +endTime) { @@ -1032,6 +1037,10 @@ const parameterCompletion = () => { Object.entries(attributes).forEach(([key, val]) => { !curComponent.value[key] && (curComponent.value[key] = val) }) + + if (!curComponent.value.timeRange.relativeToCurrentRange) { + curComponent.value.timeRange.relativeToCurrentRange = 'custom' + } } const handleCondition = item => { diff --git a/core/core-frontend/src/custom-component/v-query/RangeFilterTime.vue b/core/core-frontend/src/custom-component/v-query/RangeFilterTime.vue index b1ed8a2cc0..b1d08522aa 100644 --- a/core/core-frontend/src/custom-component/v-query/RangeFilterTime.vue +++ b/core/core-frontend/src/custom-component/v-query/RangeFilterTime.vue @@ -11,6 +11,7 @@ const props = defineProps({ dynamicWindow: false, maximumSingleQuery: 0, regularOrTrends: 'fixed', + relativeToCurrentRange: 'custom', regularOrTrendsValue: '', relativeToCurrent: 'custom', timeNum: 0, @@ -173,6 +174,85 @@ const relativeToCurrentList = computed(() => { } ] }) + +const relativeToCurrentListRange = computed(() => { + let list = [] + if (!timeRange.value) return list + switch (props.timeGranularityMultiple) { + case 'yearrange': + list = [ + { + label: '今年', + value: 'thisYear' + }, + { + label: '去年', + value: 'lastYear' + } + ] + break + case 'monthrange': + list = [ + { + label: '本月', + value: 'thisMonth' + }, + { + label: '上月', + value: 'lastMonth' + }, + { + label: '最近 3 个 月', + value: 'LastThreeMonths' + }, + { + label: '最近 6 个 月', + value: 'LastSixMonths' + }, + { + label: '最近 12 个 月', + value: 'LastTwelveMonths' + } + ] + break + case 'daterange': + case 'datetimerange': + list = [ + { + label: '今天', + value: 'today' + }, + { + label: '昨天', + value: 'yesterday' + }, + { + label: '最近 3 天', + value: 'LastThreeDays' + }, + { + label: '月初至今', + value: 'monthBeginning' + }, + { + label: '年初至今', + value: 'yearBeginning' + } + ] + break + + default: + break + } + + return [ + ...list, + { + label: '自定义', + value: 'custom' + } + ] +}) + + + { return } else if (currentDsType.value === 'API') { - for (var i = 0; i < request.apiConfiguration.length; i++) { + for (let i = 0; i < request.apiConfiguration.length; i++) { if ( request.apiConfiguration[i].deTableName === '' || request.apiConfiguration[i].deTableName === undefined || @@ -445,7 +445,7 @@ const saveDS = () => { uuid.v1().replaceAll('-', '').substring(0, 10) } request.apiConfiguration[i].jsonFields = [] - for (var j = 0; j < request.apiConfiguration[i].fields.length; j++) { + for (let j = 0; j < request.apiConfiguration[i].fields.length; j++) { request.apiConfiguration[i].fields[j].value = [] } } diff --git a/core/core-frontend/src/views/visualized/data/datasource/index.vue b/core/core-frontend/src/views/visualized/data/datasource/index.vue index 111f822778..97082ce1a2 100644 --- a/core/core-frontend/src/views/visualized/data/datasource/index.vue +++ b/core/core-frontend/src/views/visualized/data/datasource/index.vue @@ -366,7 +366,8 @@ const defaultInfo = { configuration: null, syncSetting: null, apiConfiguration: [], - weight: 0 + weight: 0, + enableDataFill: false } const nodeInfo = reactive(cloneDeep(defaultInfo)) const infoList = computed(() => { @@ -504,7 +505,8 @@ const handleNodeClick = data => { fileName, size, description, - lastSyncTime + lastSyncTime, + enableDataFill } = res.data if (configuration) { configuration = JSON.parse(Base64.decode(configuration)) @@ -531,7 +533,8 @@ const handleNodeClick = data => { apiConfiguration: apiConfigurationStr, paramsConfiguration: paramsStr, weight: data.weight, - lastSyncTime + lastSyncTime, + enableDataFill }) activeTab.value = '' activeName.value = 'config' @@ -628,7 +631,8 @@ const editDatasource = (editType?: number) => { fileName, size, description, - lastSyncTime + lastSyncTime, + enableDataFill } = res.data if (configuration) { configuration = JSON.parse(Base64.decode(configuration)) @@ -656,6 +660,7 @@ const editDatasource = (editType?: number) => { apiConfiguration: apiConfigurationStr, paramsConfiguration: paramsStr, lastSyncTime, + enableDataFill, isPlugin: arr && arr.length > 0, staticMap: arr[0]?.staticMap }) diff --git a/core/core-frontend/src/views/workbranch/ShortcutTable.vue b/core/core-frontend/src/views/workbranch/ShortcutTable.vue index 8d5ec781a5..35ebfa5ed4 100644 --- a/core/core-frontend/src/views/workbranch/ShortcutTable.vue +++ b/core/core-frontend/src/views/workbranch/ShortcutTable.vue @@ -15,6 +15,7 @@ import ShareGrid from '@/views/share/share/ShareGrid.vue' import ShareHandler from '@/views/share/share/ShareHandler.vue' import { useAppStoreWithOut } from '@/store/modules/app' import { useEmbedded } from '@/store/modules/embedded' +import { XpackComponent } from '@/components/plugin' const userStore = useUserStoreWithOut() const { resolve } = useRouter() const { t } = useI18n() @@ -139,6 +140,10 @@ const tablePaneList = ref([ { title: t('visualization.share_out'), name: 'share', disabled: false } ]) +const loadedDataFilling = data => { + tablePaneList.value.push(data) +} + const busiAuthList = getBusiListWithPermission() onMounted(() => { !!busiAuthList.length && @@ -419,6 +424,14 @@ const getEmptyDesc = (): string => { + + innerList(List ids) throws DEException; + @DePermit({"#p0+':read'"}) @GetMapping("/hidePw/{datasourceId}") DatasourceDTO hidePw(@PathVariable("datasourceId") Long datasourceId) throws DEException; diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/report/vo/ReportGridVO.java b/sdk/api/api-base/src/main/java/io/dataease/api/report/vo/ReportGridVO.java index 50c7d59ff9..7dcb97e930 100644 --- a/sdk/api/api-base/src/main/java/io/dataease/api/report/vo/ReportGridVO.java +++ b/sdk/api/api-base/src/main/java/io/dataease/api/report/vo/ReportGridVO.java @@ -27,5 +27,7 @@ public class ReportGridVO implements Serializable { private String creator; + private String updater; + private Long createTime; } diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/DataFillingApi.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/DataFillingApi.java new file mode 100644 index 0000000000..d86b7baa59 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/DataFillingApi.java @@ -0,0 +1,111 @@ +package io.dataease.api.xpack.dataFilling; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.api.report.dto.ReportInstanceMsgRequest; +import io.dataease.api.report.vo.ReportGridVO; +import io.dataease.api.xpack.dataFilling.dto.*; +import io.dataease.auth.DeApiPath; +import io.dataease.exception.DEException; +import io.dataease.extensions.datasource.dto.SimpleDatasourceDTO; +import io.dataease.model.BusiNodeRequest; +import io.dataease.model.BusiNodeVO; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; +import java.util.Map; + +import static io.dataease.constant.AuthResourceEnum.DATA_FILLING; + +@Tag(name = "数据填报") +@ApiSupport(order = 1000, author = "fit2cloud-someone") +@DeApiPath(value = "/data-filling", rt = DATA_FILLING) +public interface DataFillingApi { + + @PostMapping("tree") + List tree(@RequestBody BusiNodeRequest request) throws DEException; + + @GetMapping("/get/{id}") + DataFillingDTO get(@PathVariable("id") Long id); + + @PostMapping("/move") + DataFillingDTO move(@RequestBody DataFillingDTO dataFillingDTO); + + @PostMapping("/save") + DataFillingDTO save(@RequestBody DataFillingDTO dataFillingDTO) throws Exception; + + @PostMapping("/rename") + DataFillingDTO rename(@RequestBody DataFillingDTO dataFillingDTO); + + @GetMapping("delete/{id}") + void delete(@PathVariable("id") Long id); + + @GetMapping("/datasource/list") + List listDatasourceList(); + + @PostMapping("/form/{optionDatasource}/options") + List listColumnData(@PathVariable("optionDatasource") Long optionDatasource, @RequestBody DatasourceOptionsRequest request) throws Exception; + + @PostMapping("/form/{id}/tableData") + DataFillFormTableDataResponse tableData(@PathVariable Long id, @RequestBody DataFillFormTableDataRequest request) throws Exception; + + @GetMapping("/form/{formId}/delete/{id}") + void deleteRowData(@PathVariable Long formId, @PathVariable Long id) throws Exception; + + @PostMapping("/form/{formId}/batch-delete") + void batchDeleteRowData(@PathVariable Long formId, @RequestBody List ids) throws Exception; + + @PostMapping("/form/{formId}/rowData/save") + DataFillFormTableDataResponse saveRowData(@PathVariable Long formId, @RequestBody Map data) throws Exception; + + + @GetMapping("/task/info/{taskId}") + TaskInfoVO info(@PathVariable("taskId") Long taskId); + + + @PostMapping("/task/save") + Long save(@RequestBody TaskInfoVO task); + + @PostMapping("/task/logMsg") + String logMsg(@RequestBody ReportInstanceMsgRequest request); + + @PostMapping("/task/page/{goPage}/{pageSize}") + IPage taskPager(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody DfTaskInfoRequest request); + + @PostMapping("/sub-task/page/{goPage}/{pageSize}") + IPage subTaskPager(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody DfSubTaskInfoRequest request); + + @PostMapping("/task/delete") + void batchDeleteTask(@RequestBody List ids) throws Exception; + + @GetMapping("/task/{id}/stop") + void stopTask(@PathVariable Long id) throws Exception; + + @GetMapping("/task/{id}/start") + void startTask(@PathVariable Long id) throws Exception; + + @PostMapping("/sub-task/delete") + void batchDeleteSubTask(@RequestBody List ids) throws Exception; + + @GetMapping("/sub-task/{id}/users/list/{type}") + List> listSubTaskUser(@PathVariable Long id, @PathVariable String type) throws Exception; + + @PostMapping("/user-task") + List listUserTask(@RequestBody DfUserTaskRequest request) throws Exception; + + @GetMapping("/user-task/list/{id}") + DfUserTaskData listUserTaskData(@PathVariable Long id) throws Exception; + + @PostMapping("/user-task/saveData/{id}") + DataFillFormTableDataResponse saveFormRowData(@PathVariable Long id, @RequestBody Map data) throws Exception; + + + @PostMapping("/log/page/{goPage}/{pageSize}") + IPage taskPager(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody DfCommitLogRequest request); + + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/ColumnOption.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/ColumnOption.java new file mode 100644 index 0000000000..676eccf783 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/ColumnOption.java @@ -0,0 +1,23 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ColumnOption implements Serializable { + + @Serial + private static final long serialVersionUID = -422787778573500470L; + + private String name; + + private Object value; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataRequest.java new file mode 100644 index 0000000000..a843ddfff8 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataRequest.java @@ -0,0 +1,31 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + + +@Data +@Accessors(chain = true) +public class DataFillFormTableDataRequest implements Serializable { + + @Serial + private static final long serialVersionUID = -314618516232771747L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private long currentPage; + + private long pageSize; + + private boolean withoutLogs = false; + + private List primaryKeyValueList; + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataResponse.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataResponse.java new file mode 100644 index 0000000000..4918a5b904 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillFormTableDataResponse.java @@ -0,0 +1,28 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Accessors(chain = true) +public class DataFillFormTableDataResponse implements Serializable { + + @Serial + private static final long serialVersionUID = -6463885075511811532L; + + private Object data; + + private String fields; + + private long total; + + private long currentPage; + + private long pageSize; + + private String key; + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillingDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillingDTO.java new file mode 100644 index 0000000000..e7187cdc61 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DataFillingDTO.java @@ -0,0 +1,91 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +@Data +public class DataFillingDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * folder/form 目录或文件夹 + */ + private String nodeType; + + /** + * 表名 + */ + private String tableName; + + /** + * 数据源 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasource; + + /** + * 表单内容 + */ + private String forms; + + /** + * 是否创建索引 + */ + private Boolean createIndex; + + /** + * 索引 + */ + private String tableIndexes; + + /** + * 创建人 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long createBy; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 更新人 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long updateBy; + + /** + * 更新时间 + */ + private Long updateTime; + + private String creator; + private String updater; + + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DatasourceOptionsRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DatasourceOptionsRequest.java new file mode 100644 index 0000000000..c20c24b4c5 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DatasourceOptionsRequest.java @@ -0,0 +1,11 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.Getter; + +@Getter +public class DatasourceOptionsRequest { + + private String optionTable; + private String optionColumn; + private String optionOrder; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLog.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLog.java new file mode 100644 index 0000000000..60962f88a3 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLog.java @@ -0,0 +1,37 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Accessors(chain = true) +public class DfCommitLog implements Serializable { + + @Serial + private static final long serialVersionUID = 3175509273615697110L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long formId; + + @JsonSerialize(using = ToStringSerializer.class) + private Long dataId; + + /** + * 操作 0删除 1插入 2更新 + */ + private Integer operate; + + private Long commitBy; + + private String committer; + + private Long commitTime; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLogRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLogRequest.java new file mode 100644 index 0000000000..f5de44a938 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfCommitLogRequest.java @@ -0,0 +1,17 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class DfCommitLogRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 8186544152722934919L; + + private Long formId; + + private Integer operate; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskInfoRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskInfoRequest.java new file mode 100644 index 0000000000..600a2a1831 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskInfoRequest.java @@ -0,0 +1,18 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class DfSubTaskInfoRequest implements Serializable { + @Serial + private static final long serialVersionUID = 3478936079850972546L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long taskId; + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskVo.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskVo.java new file mode 100644 index 0000000000..17c17cc84b --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfSubTaskVo.java @@ -0,0 +1,56 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +public class DfSubTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 7440756474905083085L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long taskId; + + private Long startTime; + + private Long endTime; + + /** + * 任务下发状态 + */ + private Integer execStatus; + + /** + * 任务状态 + * 1:进行中/ 0:已过期 根据endTime判断 + */ + private Integer status; + + /** + * 所有任务项 subInstance 个数 + */ + private int totalCount; + private int unfinishedCount; + + /** + * 完成率 + * (totalCount - unfinishedCount) / totalCount + */ + private BigDecimal finishedRate; + + private int totalUserCount; + private int unfinishedUserCount; + + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfTaskInfoRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfTaskInfoRequest.java new file mode 100644 index 0000000000..955028e675 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfTaskInfoRequest.java @@ -0,0 +1,25 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +public class DfTaskInfoRequest implements Serializable { + @Serial + private static final long serialVersionUID = 3478936079850972546L; + + private List uidList; + + private List lastStatusList; + + private List statusList; + + private List timeList; + + private String keyword; + + private Boolean timeDesc; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskData.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskData.java new file mode 100644 index 0000000000..8bce741982 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskData.java @@ -0,0 +1,56 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.dataease.utils.LongArray2StringSerialize; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class DfUserTaskData implements Serializable { + @Serial + private static final long serialVersionUID = -3635512734559897349L; + + @Data + @Accessors(chain = true) + public static class DfSubInstance implements Serializable { + @Serial + private static final long serialVersionUID = 4847820854888692033L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + @JsonSerialize(using = ToStringSerializer.class) + private Long taskId; + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + @JsonSerialize(using = ToStringSerializer.class) + private Long uid; + @JsonSerialize(using = ToStringSerializer.class) + private Long formId; + @JsonSerialize(using = ToStringSerializer.class) + private Long dataId; + + private Long finishTime; + private Integer status; + + } + + @JsonSerialize(using = ToStringSerializer.class) + private Long formId; + private String formTitle; + @JsonSerialize(using = LongArray2StringSerialize.class) + private List dataIds; + + private List subInstances; + + private String form; + + private String formExtSetting; + + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskRequest.java new file mode 100644 index 0000000000..42a8bcdf2b --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskRequest.java @@ -0,0 +1,19 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Accessors(chain = true) +public class DfUserTaskRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 3930338226463461223L; + + private String type; + + private String taskName; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskVo.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskVo.java new file mode 100644 index 0000000000..0d369925a6 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/DfUserTaskVo.java @@ -0,0 +1,42 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.dataease.utils.LongArray2StringSerialize; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class DfUserTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 2573431692696582629L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long taskId; + + @JsonSerialize(using = ToStringSerializer.class) + private Long formId; + + private String taskName; + + private Long startTime; + + private Long endTime; + + private Long finishTime; + + @JsonSerialize(using = ToStringSerializer.class) + private Long assignBy; + + private String assigner; + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoGridVO.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoGridVO.java new file mode 100644 index 0000000000..d3c9ce1423 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoGridVO.java @@ -0,0 +1,38 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.dataease.utils.LongArray2StringSerialize; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class TaskInfoGridVO implements Serializable { + + @Serial + private static final long serialVersionUID = -5178055146669970633L; + @JsonSerialize(using= ToStringSerializer.class) + private Long id; + + private String name; + + private Long lastExecTime; + + private Integer lastExecStatus; + + private Integer status; + + private Long nextExecTime; + + private String creatBy; + + private String creator; + + private Long createTime; + +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoVO.java b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoVO.java new file mode 100644 index 0000000000..79c934c8cc --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/xpack/dataFilling/dto/TaskInfoVO.java @@ -0,0 +1,73 @@ +package io.dataease.api.xpack.dataFilling.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.dataease.utils.LongArray2StringSerialize; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class TaskInfoVO implements Serializable { + + @Serial + private static final long serialVersionUID = 7074759598819246816L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long formId; + + private String name; + + private List reciFlagList; + + @JsonSerialize(using = LongArray2StringSerialize.class) + private List uidList; + + @JsonSerialize(using = LongArray2StringSerialize.class) + private List ridList; + + private Integer fillType; + + private Integer fitType; + + private String fitColumn; + + private Integer rateType; + + private String rateVal; + + private Long startTime; + + private Long endTime; + + @JsonSerialize(using = ToStringSerializer.class) + private Long createBy; + private String creator; + private Long createTime; + + @JsonSerialize(using = ToStringSerializer.class) + private Long updateBy; + private String updater; + private Long updateTime; + + private Integer publishRangeTime; + + private Integer publishRangeTimeType; + + private Integer status; + + private Integer lastExecStatus; + private Long lastExecTime; + private Long nextExecTime; + + + private String formExtSetting; + +} diff --git a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/org/api/OrgApi.java b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/org/api/OrgApi.java index 7f8ec71fe4..b42df9cc9f 100644 --- a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/org/api/OrgApi.java +++ b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/org/api/OrgApi.java @@ -61,4 +61,8 @@ public interface OrgApi { @Operation(hidden = true) @GetMapping("/detail/{oid}") OrgDetailVO detail(@PathVariable("oid") Long oid); + + @Operation(hidden = true) + @GetMapping("/subOrgs") + List subOrgs(); } diff --git a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/api/UserApi.java b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/api/UserApi.java index 993e470c5f..8ffbbdc5c5 100644 --- a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/api/UserApi.java +++ b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/user/api/UserApi.java @@ -190,4 +190,16 @@ public interface UserApi { @GetMapping("/invalidPwd") InvalidPwdVO invalidPwd(); + @Hidden + @PostMapping("/subOrgUser") + List subOrgUser(@RequestBody List oidList); + + List getRecipientUserIds(UserReciRequest request); + + List getUserIdByAccount(String account); + + List getUserIdByName(String name); + + List> listUserInfosByIds(List ids); + } diff --git a/sdk/common/src/main/java/io/dataease/constant/AuthResourceEnum.java b/sdk/common/src/main/java/io/dataease/constant/AuthResourceEnum.java index bef3c219ee..40cdd10ff2 100644 --- a/sdk/common/src/main/java/io/dataease/constant/AuthResourceEnum.java +++ b/sdk/common/src/main/java/io/dataease/constant/AuthResourceEnum.java @@ -2,7 +2,7 @@ package io.dataease.constant; public enum AuthResourceEnum { - PANEL(2, 1), SCREEN(3, 2), DATASET(5, 3), DATASOURCE(6, 4), SYSTEM(7, 0), USER(8, 5), ROLE(8, 6), ORG(9, 7), SYNC_DATASOURCE(23, 8), TASK(24, 9), SUMMARY(22, 10); + PANEL(2, 1), SCREEN(3, 2), DATASET(5, 3), DATASOURCE(6, 4), SYSTEM(7, 0), USER(8, 5), ROLE(8, 6), ORG(9, 7), SYNC_DATASOURCE(23, 8), TASK(24, 9), SUMMARY(22, 10), DATA_FILLING(60, 11); private long menuId; diff --git a/sdk/common/src/main/java/io/dataease/constant/BusiResourceEnum.java b/sdk/common/src/main/java/io/dataease/constant/BusiResourceEnum.java index 7d582d0ce8..fcb1143930 100644 --- a/sdk/common/src/main/java/io/dataease/constant/BusiResourceEnum.java +++ b/sdk/common/src/main/java/io/dataease/constant/BusiResourceEnum.java @@ -2,7 +2,7 @@ package io.dataease.constant; public enum BusiResourceEnum { - PANEL(1), SCREEN(2), DATASET(3), DATASOURCE(4); + PANEL(1), SCREEN(2), DATASET(3), DATASOURCE(4), DATA_FILLING(8); private int flag; diff --git a/sdk/common/src/main/java/io/dataease/constant/DadaFillingFinishTaskEnum.java b/sdk/common/src/main/java/io/dataease/constant/DadaFillingFinishTaskEnum.java new file mode 100644 index 0000000000..532e1bf3a4 --- /dev/null +++ b/sdk/common/src/main/java/io/dataease/constant/DadaFillingFinishTaskEnum.java @@ -0,0 +1,29 @@ +package io.dataease.constant; + +import java.util.Arrays; + +public enum DadaFillingFinishTaskEnum { + + OPEN(0), FINISHED(1); + + private Integer flag; + + public Integer getFlag() { + return flag; + } + + public void setFlag(Integer flag) { + this.flag = flag; + } + + DadaFillingFinishTaskEnum(Integer flag) { + this.flag = flag; + } + + DadaFillingFinishTaskEnum() { + } + + public static DadaFillingFinishTaskEnum fromValue(Integer flag) { + return Arrays.stream(values()).filter(v -> v.flag.equals(flag)).findFirst().get(); + } +} diff --git a/sdk/common/src/main/java/io/dataease/utils/LongArray2StringSerialize.java b/sdk/common/src/main/java/io/dataease/utils/LongArray2StringSerialize.java new file mode 100644 index 0000000000..0858600837 --- /dev/null +++ b/sdk/common/src/main/java/io/dataease/utils/LongArray2StringSerialize.java @@ -0,0 +1,23 @@ +package io.dataease.utils; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class LongArray2StringSerialize extends JsonSerializer> { + + @Override + public void serialize(List longs, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + List list = new ArrayList<>(); + for (Long str : longs) { + if (str != null) { + list.add(str.toString()); + } + } + jsonGenerator.writeObject(list); + } +} diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceDTO.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceDTO.java index 81ee90d0b4..79af9509e6 100644 --- a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceDTO.java +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceDTO.java @@ -89,4 +89,6 @@ public class DatasourceDTO implements Serializable { * 任务状态 */ private String taskStatus; + + private Boolean enableDataFill; } diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceRequest.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceRequest.java index 1eb97c02a9..e8392f7655 100644 --- a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceRequest.java +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/DatasourceRequest.java @@ -4,6 +4,7 @@ import lombok.Data; import org.springframework.util.StringUtils; import java.io.Serializable; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -24,6 +25,7 @@ public class DatasourceRequest implements Serializable { private boolean previewData = false; private boolean totalPageFlag; private Map dsList; + private List tableFieldWithValues; public DatasourceRequest() { } diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/SimpleDatasourceDTO.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/SimpleDatasourceDTO.java new file mode 100644 index 0000000000..4c0c938d77 --- /dev/null +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/SimpleDatasourceDTO.java @@ -0,0 +1,24 @@ +package io.dataease.extensions.datasource.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class SimpleDatasourceDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 2255370172449547802L; + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + private String name; + private String type; + private String typeAlias; + private String status; + private Boolean enableDataFill; +} diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableField.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableField.java index ba0f94468f..fb2474b6c2 100644 --- a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableField.java +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableField.java @@ -19,7 +19,9 @@ public class TableField { private Integer deExtractType; private int extField; private String jsonPath; + private boolean primary; List value; + private int inCount; } diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableFieldWithValue.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableFieldWithValue.java new file mode 100644 index 0000000000..211d94492e --- /dev/null +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/dto/TableFieldWithValue.java @@ -0,0 +1,29 @@ +package io.dataease.extensions.datasource.dto; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; + +@Getter +@Setter +@Accessors(chain = true) +public class TableFieldWithValue implements Serializable { + @Serial + private static final long serialVersionUID = -8852504196142402103L; + + private Object value; + private String filedName; + private String typeName; + private Integer type; + + public static TableFieldWithValue copy(TableFieldWithValue tableFieldWithValue) { + return new TableFieldWithValue() + .setValue(tableFieldWithValue.getValue()) + .setFiledName(tableFieldWithValue.getFiledName()) + .setTypeName(tableFieldWithValue.getTypeName()) + .setType(tableFieldWithValue.getType()); + } +} diff --git a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/provider/Provider.java b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/provider/Provider.java index da431d3a75..ab7f5c9251 100644 --- a/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/provider/Provider.java +++ b/sdk/extensions/extensions-datasource/src/main/java/io/dataease/extensions/datasource/provider/Provider.java @@ -92,6 +92,11 @@ public abstract class Provider { */ public abstract void hidePW(DatasourceDTO datasourceDTO); + public abstract void exec(DatasourceRequest datasourceRequest) throws DEException; + + public abstract int executeUpdate(DatasourceRequest datasourceRequest) throws DEException; + + @Getter private static final Map lPorts = new HashMap<>(); @Getter