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 d2f6d4d8c5..926674c050 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
@@ -20,7 +20,7 @@ i18n_menu.org=\u7EC4\u7EC7\u7BA1\u7406
i18n_menu.auth=\u6743\u9650\u914D\u7F6E
i18n_menu.sync=\u540C\u6B65\u7BA1\u7406
i18n_menu.summary=\u6982\u89C8
-i18n_menu.ds=\u6570\u636E\u6E90\u7BA1\u7406
+i18n_menu.ds=\u6570\u636e\u8fde\u63a5\u7ba1\u7406
i18n_menu.task=\u4EFB\u52A1\u7BA1\u7406
i18n_menu.embedded=\u5D4C\u5165\u5F0F\u7BA1\u7406
i18n_menu.platform=\u5E73\u53F0\u5BF9\u63A5
diff --git a/core/core-frontend/src/api/sync/syncDatasource.ts b/core/core-frontend/src/api/sync/syncDatasource.ts
new file mode 100644
index 0000000000..5a9686c8fd
--- /dev/null
+++ b/core/core-frontend/src/api/sync/syncDatasource.ts
@@ -0,0 +1,47 @@
+import request from '@/config/axios'
+
+export const sourceDsPageApi = (page: number, limit: number, data) => {
+ return request.post({ url: `/sync/datasource/source/pager/${page}/${limit}`, data })
+}
+
+export const targetDsPageApi = (page: number, limit: number, data) => {
+ return request.post({ url: `/sync/datasource/target/pager/${page}/${limit}`, data })
+}
+export const latestUseApi = () => {
+ return request.post({ url: '/sync/datasource/latestUse', data: {} })
+}
+
+export const validateApi = data => {
+ return request.post({ url: '/sync/datasource/validate', data })
+}
+
+export const getSchemaApi = data => {
+ return request.post({ url: '/sync/datasource/getSchema', data })
+}
+
+export const saveApi = data => {
+ return request.post({ url: '/sync/datasource/save', data })
+}
+
+export const getByIdApi = (id: string) => {
+ return request.get({ url: `/sync/datasource/get/${id}` })
+}
+
+export const updateApi = data => {
+ return request.post({ url: '/sync/datasource/update', data })
+}
+
+export const deleteByIdApi = (id: string) => {
+ return request.post({ url: `/sync/datasource/delete/${id}` })
+}
+
+export const batchDelApi = (ids: string[]) => {
+ return request.post({ url: `/sync/datasource/batchDel`, data: ids })
+}
+
+/**
+ * 获取源数据库字段集合以及目标数据库数据类型集合
+ */
+export const getFieldListApi = data => {
+ return request.post({ url: `/sync/datasource/fields`, data })
+}
diff --git a/core/core-frontend/src/api/sync/syncSummary.ts b/core/core-frontend/src/api/sync/syncSummary.ts
new file mode 100644
index 0000000000..801c83f963
--- /dev/null
+++ b/core/core-frontend/src/api/sync/syncSummary.ts
@@ -0,0 +1,26 @@
+import request from '@/config/axios'
+
+interface IResourceCount {
+ jobCount: number
+ datasourceCount: number
+ jobLogCount: number
+}
+
+export const getResourceCount = () => {
+ return request
+ .get({
+ url: 'sync/summary/resourceCount',
+ method: 'get'
+ })
+ .then(res => {
+ return res.data as IResourceCount
+ })
+}
+
+export const getJobLogLienChartInfo = () => {
+ return request.post({
+ url: '/sync/summary/logChartData',
+ method: 'post',
+ data: ''
+ })
+}
diff --git a/core/core-frontend/src/api/sync/syncTask.ts b/core/core-frontend/src/api/sync/syncTask.ts
new file mode 100644
index 0000000000..d359119601
--- /dev/null
+++ b/core/core-frontend/src/api/sync/syncTask.ts
@@ -0,0 +1,224 @@
+import request from '@/config/axios'
+
+export interface IGetTaskInfoReq {
+ id?: string
+ name?: string
+}
+
+export interface ITaskInfoInsertReq {
+ [key: string]: any
+}
+
+export interface ISchedulerOption {
+ interval: number
+ unit: string
+}
+
+export interface ISource {
+ type: string
+ query: string
+ tables: string
+ datasourceId: string
+ tableExtract: string
+ dsTableList?: IDsTable[]
+ dsList?: []
+ fieldList?: ITableField[]
+ targetFieldTypeList?: string[]
+ incrementCheckbox?: string
+ incrementField?: string
+}
+
+export interface ITableField {
+ id: string
+ fieldSource: string
+ fieldName: string
+ fieldType: string
+ remarks: string
+ fieldSize: number
+ fieldPk: boolean
+ fieldIndex: boolean
+}
+
+export interface ITargetProperty {
+ /**
+ * 启用分区on
+ */
+ partitionEnable: string
+ /**
+ * 分区类型
+ * DateRange 日期
+ * NumberRange 数值
+ * List 列
+ */
+ partitionType: string
+ /**
+ * 启用动态分区on
+ */
+ dynamicPartitionEnable: string
+ /**
+ * 动态分区结束偏移量
+ */
+ dynamicPartitionEnd: number
+ /**
+ * 动态分区间隔单位
+ * HOUR WEEK DAY MONTH YEAR
+ */
+ dynamicPartitionTimeUnit: string
+ /**
+ * 手动分区列值
+ * 多个以','隔开
+ */
+ manualPartitionColumnValue: string
+ /**
+ * 手动分区数值区间开始值
+ */
+ manualPartitionStart: number
+ /**
+ * 手动分区数值区间结束值
+ */
+ manualPartitionEnd: number
+ /**
+ * 手动分区数值区间间隔
+ */
+ manualPartitionInterval: number
+ /**
+ * 手动分区日期区间
+ * 2023-09-08 - 2023-09-15
+ */
+ manualPartitionTimeRange: string
+ /**
+ * 手动分区日期区间间隔单位
+ */
+ manualPartitionTimeUnit: string
+ /**
+ * 分区字段
+ */
+ partitionColumn: string
+}
+
+export interface ITarget {
+ createTable?: string
+ type: string
+ fieldList: ITableField[]
+ tableName: string
+ datasourceId: string
+ targetProperty: string
+ dsList?: []
+ multipleSelection?: ITableField[]
+ property: ITargetProperty
+}
+
+export class ITaskInfoRes {
+ id: string
+
+ name: string
+
+ schedulerType: string
+
+ schedulerConf: string
+
+ schedulerOption: ISchedulerOption
+
+ taskKey: string
+
+ desc: string
+
+ executorTimeout: number
+
+ executorFailRetryCount: number
+
+ source: ISource
+
+ target: ITarget
+
+ status: string
+ startTime: string
+ stopTime: string
+
+ constructor(
+ id: string,
+ name: string,
+ schedulerType: string,
+ schedulerConf: string,
+ taskKey: string,
+ desc: string,
+ executorTimeout: number,
+ executorFailRetryCount: number,
+ source: ISource,
+ target: ITarget,
+ status: string,
+ startTime: string,
+ stopTime: string,
+ schedulerOption: ISchedulerOption
+ ) {
+ this.id = id
+ this.name = name
+ this.schedulerType = schedulerType
+ this.schedulerConf = schedulerConf
+ this.taskKey = taskKey
+ this.desc = desc
+ this.executorTimeout = executorTimeout
+ this.executorFailRetryCount = executorFailRetryCount
+ this.source = source
+ this.target = target
+ this.status = status
+ this.startTime = startTime
+ this.stopTime = stopTime
+ this.schedulerOption = schedulerOption
+ }
+}
+
+export interface ITaskInfoUpdateReq {
+ [key: string]: any
+}
+
+export interface IDsTable {
+ datasourceId: string
+ name: string
+ remark: string
+ enableCheck: string
+ datasetPath: string
+}
+
+export const getDatasourceListByTypeApi = (type: string) => {
+ return request.get({ url: `/sync/datasource/list/${type}` })
+}
+export const getTaskInfoListApi = (current: number, size: number, data) => {
+ return request.post({ url: `/sync/task/pager/${current}/${size}`, data: data })
+}
+
+export const executeOneApi = (id: string) => {
+ return request.get({ url: `/sync/task/execute/${id}` })
+}
+
+export const startTaskApi = (id: string) => {
+ return request.get({ url: `/sync/task/start/${id}` })
+}
+
+export const stopTaskApi = (id: string) => {
+ return request.get({ url: `/sync/task/stop/${id}` })
+}
+
+export const addApi = (data: ITaskInfoInsertReq) => {
+ return request.post({ url: `/sync/task/add`, data: data })
+}
+
+export const removeApi = (taskId: string) => {
+ return request.delete({ url: `/sync/task/remove/${taskId}` })
+}
+
+export const batchRemoveApi = (taskIds: string[]) => {
+ return request.post({ url: `/sync/task/batch/del`, data: taskIds })
+}
+
+export const modifyApi = (data: ITaskInfoUpdateReq) => {
+ return request.post({ url: `/sync/task/update`, data: data })
+}
+
+export const findTaskInfoByIdApi = (taskId: string) => {
+ return request.get({ url: `/sync/task/get/${taskId}` })
+}
+
+export const getDatasourceTableListApi = (dsId: string) => {
+ return request.get({ url: `/sync/datasource/table/list/${dsId}` })
+}
diff --git a/core/core-frontend/src/api/sync/syncTaskLog.ts b/core/core-frontend/src/api/sync/syncTaskLog.ts
new file mode 100644
index 0000000000..d9b6ffc3f6
--- /dev/null
+++ b/core/core-frontend/src/api/sync/syncTaskLog.ts
@@ -0,0 +1,20 @@
+import request from '@/config/axios'
+
+export const getTaskLogListApi = (current: number, size: number, data: any) => {
+ return request.post({
+ url: `/sync/task/log/pager/${current}/${size}`,
+ data: data
+ })
+}
+
+export const removeApi = (logId: string) => {
+ return request.delete({ url: `/sync/task/log/delete/${logId}` })
+}
+
+export const getTaskLogDetailApi = (logId: string, fromLineNum: number) => {
+ return request.get({ url: `/sync/task/log/detail/${logId}/${fromLineNum}` })
+}
+
+export const clear = (clearData: {}) => {
+ return request.post({ url: `/sync/task/log/clear`, data: clearData })
+}
diff --git a/core/core-frontend/src/assets/svg/icon_sync_close_log_details.svg b/core/core-frontend/src/assets/svg/icon_sync_close_log_details.svg
new file mode 100644
index 0000000000..7c0dc4cbc5
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_close_log_details.svg
@@ -0,0 +1,3 @@
+
diff --git a/core/core-frontend/src/assets/svg/icon_sync_datasource.svg b/core/core-frontend/src/assets/svg/icon_sync_datasource.svg
new file mode 100644
index 0000000000..1e3fc9db1d
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_datasource.svg
@@ -0,0 +1,16 @@
+
diff --git a/core/core-frontend/src/assets/svg/icon_sync_log_number.svg b/core/core-frontend/src/assets/svg/icon_sync_log_number.svg
new file mode 100644
index 0000000000..49869e0981
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_log_number.svg
@@ -0,0 +1,17 @@
+
diff --git a/core/core-frontend/src/assets/svg/icon_sync_logs_outlined.svg b/core/core-frontend/src/assets/svg/icon_sync_logs_outlined.svg
new file mode 100644
index 0000000000..e310452c05
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_logs_outlined.svg
@@ -0,0 +1,3 @@
+
diff --git a/core/core-frontend/src/assets/svg/icon_sync_target_to_datasource.svg b/core/core-frontend/src/assets/svg/icon_sync_target_to_datasource.svg
new file mode 100644
index 0000000000..d84bc12a9e
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_target_to_datasource.svg
@@ -0,0 +1,3 @@
+
diff --git a/core/core-frontend/src/assets/svg/icon_sync_task_number.svg b/core/core-frontend/src/assets/svg/icon_sync_task_number.svg
new file mode 100644
index 0000000000..bce4a1e198
--- /dev/null
+++ b/core/core-frontend/src/assets/svg/icon_sync_task_number.svg
@@ -0,0 +1,17 @@
+
diff --git a/core/core-frontend/src/components/drawer-filter/src/DrawerTimeFilter.vue b/core/core-frontend/src/components/drawer-filter/src/DrawerTimeFilter.vue
index 8fd955d120..68ef025353 100644
--- a/core/core-frontend/src/components/drawer-filter/src/DrawerTimeFilter.vue
+++ b/core/core-frontend/src/components/drawer-filter/src/DrawerTimeFilter.vue
@@ -1,46 +1,66 @@
@@ -48,108 +68,42 @@ defineExpose({
{{ title }}
- {{ $t(ele.name) }}
-
-
-
-
-
-
-
-
-
-
- 更多
-
-
-
-
+
-
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 14b167ef36..13853900ea 100644
--- a/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue
+++ b/core/core-frontend/src/components/drawer-main/src/DrawerMain.vue
@@ -14,7 +14,8 @@ const props = defineProps({
type: propTypes.string,
field: propTypes.string,
option: propTypes.array,
- title: propTypes.string
+ title: propTypes.string,
+ property: propTypes.shape({})
})
),
title: propTypes.string
@@ -126,7 +127,8 @@ defineExpose({
:ref="el => (myRefs[index] = el)"
v-if="component.type === 'time'"
:title="component.title"
- @filter-change="v => filterChange(v, component.field, 'eq')"
+ :property="component.property"
+ @filter-change="v => filterChange(v, component.field, component.operator)"
/>
diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts
index 7c29dca6a3..82fd13f4f2 100644
--- a/core/core-frontend/src/locales/zh-CN.ts
+++ b/core/core-frontend/src/locales/zh-CN.ts
@@ -2131,5 +2131,56 @@ export default {
template_manage: {
name_already_exists_type: '分类名称已存在',
the_same_category: '同一分类下,该模板名称已存在'
+ },
+ sync_manage: {
+ title: '同步管理',
+ ds_search_placeholder: '搜索名称,描述'
+ },
+ sync_datasource: {
+ title: '数据连接管理',
+ source_ds: '源数据源',
+ target_ds: '目标数据源',
+ add_source_ds: '@:common.add@:sync_datasource.source_ds',
+ add_target_ds: '@:common.add@:sync_datasource.target_ds',
+ name: '名称',
+ desc: '描述',
+ type: '类型',
+ status: '状态',
+ create_time: '创建时间',
+ update_time: '更新时间',
+ operation: '操作',
+ edit: '编辑',
+ delete: '删除',
+ confirm_batch_delete_target_ds: '确定删除{0}个目标数据源吗?',
+ confirm_batch_delete_source_ds: '确定删除{0}个源数据源吗?'
+ },
+ sync_task: {
+ title: '任务管理',
+ list: '任务列表',
+ log_list: '任务日志',
+ add_task: '添加任务',
+ name: '名称',
+ desc: '描述',
+ status: '状态',
+ create_time: '创建时间',
+ update_time: '更新时间',
+ operation: '操作',
+ edit: '编辑',
+ delete: '删除',
+ start: '启动',
+ stop: '停止',
+ trigger_last_time: '上次执行时间',
+ trigger_next_time: '下次执行时间',
+ status_success: '成功',
+ status_running: '执行中',
+ status_failed: '失败',
+ status_stopped: '已停止',
+ status_waiting: '等待执行',
+ status_done: '执行结束',
+ status_suspend: '暂停',
+ running_one: '执行一次',
+ keep_going: '继续',
+ log: '日志',
+ show_log: '查看日志'
}
}
diff --git a/sdk/api/api-sync/pom.xml b/sdk/api/api-sync/pom.xml
new file mode 100644
index 0000000000..5e36463122
--- /dev/null
+++ b/sdk/api/api-sync/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ api
+ io.dataease
+ 2.1.0
+
+ 4.0.0
+
+ api-sync
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/api/SyncDatasourceApi.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/api/SyncDatasourceApi.java
new file mode 100644
index 0000000000..4e5d7c6cd5
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/api/SyncDatasourceApi.java
@@ -0,0 +1,80 @@
+package io.dataease.api.sync.datasource.api;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.dataease.api.sync.datasource.dto.DBTableDTO;
+import io.dataease.api.sync.datasource.dto.GetDatasourceRequest;
+import io.dataease.api.sync.datasource.dto.SyncDatasourceDTO;
+import io.dataease.api.sync.datasource.vo.SyncDatasourceVO;
+import io.dataease.auth.DeApiPath;
+import io.dataease.auth.DePermit;
+import io.dataease.exception.DEException;
+import io.dataease.request.BaseGridRequest;
+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.SYNC_DATASOURCE;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/20 10:14
+ **/
+@DeApiPath(value = "/sync/datasource", rt = SYNC_DATASOURCE)
+public interface SyncDatasourceApi {
+
+ @DePermit("m:read")
+ @PostMapping("/source/pager/{goPage}/{pageSize}")
+ IPage sourcePager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
+
+ @DePermit("m:read")
+ @PostMapping("/target/pager/{goPage}/{pageSize}")
+ IPage targetPager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
+
+ @PostMapping("/save")
+ void save(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
+
+ @PostMapping("/update")
+ void update(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
+
+ @PostMapping("/delete/{datasourceId}")
+ void delete(@PathVariable("datasourceId") String datasourceId) throws DEException;
+
+ @GetMapping("/types")
+ Object datasourceTypes() throws DEException;
+
+ @PostMapping("/validate")
+ String validate(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
+
+ @PostMapping("/getSchema")
+ List getSchema(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
+
+ @DePermit({"#p0+':manage'"})
+ @GetMapping("/validate/{datasourceId}")
+ SyncDatasourceDTO validate(@PathVariable("datasourceId") String datasourceId) throws DEException;
+
+ @PostMapping("/latestUse")
+ List latestUse();
+
+ @GetMapping("/get/{datasourceId}")
+ SyncDatasourceDTO get(@PathVariable("datasourceId") String datasourceId) throws DEException;
+
+ @PostMapping("/batchDel")
+ void batchDel(@RequestBody List ids) throws DEException;
+
+ @PostMapping("/fields")
+ Map getFields(@RequestBody GetDatasourceRequest getDsRequest) throws DEException ;
+
+ @GetMapping("/list/{type}")
+ List listByType(@PathVariable("type") String type) throws DEException;
+
+ @GetMapping("/table/list/{dsId}")
+ List getTableList(@PathVariable("dsId") String dsId) throws DEException;
+
+
+
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/DBTableDTO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/DBTableDTO.java
new file mode 100644
index 0000000000..a8112d8e26
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/DBTableDTO.java
@@ -0,0 +1,18 @@
+package io.dataease.api.sync.datasource.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Author gin
+ * @Date 2021/4/30 10:57 上午
+ */
+@Getter
+@Setter
+public class DBTableDTO {
+ private String datasourceId;
+ private String name;
+ private String remark;
+ private boolean enableCheck;
+ private String datasetPath;
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/GetDatasourceRequest.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/GetDatasourceRequest.java
new file mode 100644
index 0000000000..7387082ca2
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/GetDatasourceRequest.java
@@ -0,0 +1,25 @@
+package io.dataease.api.sync.datasource.dto;
+
+import lombok.Data;
+
+@Data
+public class GetDatasourceRequest extends SyncDatasourceDTO {
+
+ /**
+ * 查询sql
+ */
+ private String query;
+ /**
+ * 表名
+ */
+ private String table;
+ /**
+ * 表格的抽取数据方式
+ */
+ private boolean tableExtract;
+ /**
+ * 不为空时,获取源数据库表字段,将转换为doris的数据类型
+ */
+ private String targetDbType;
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/SyncDatasourceDTO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/SyncDatasourceDTO.java
new file mode 100644
index 0000000000..8c8146f655
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/dto/SyncDatasourceDTO.java
@@ -0,0 +1,61 @@
+package io.dataease.api.sync.datasource.dto;
+
+import lombok.Data;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/20 11:14
+ **/
+@Data
+public class SyncDatasourceDTO {
+
+ /**
+ * ID
+ */
+ private String id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 描述
+ */
+ private String desc;
+
+ /**
+ * 类型
+ */
+ private String type;
+
+ /**
+ * 详细信息
+ */
+ private String configuration;
+
+ /**
+ * Create timestamp
+ */
+ private Long createTime;
+
+ /**
+ * Update timestamp
+ */
+ private Long updateTime;
+
+ /**
+ * 创建人ID
+ */
+ private Long createBy;
+ private String createByUserName;
+
+ /**
+ * 状态
+ */
+ private String status;
+
+ private String statusRemark;
+
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/vo/SyncDatasourceVO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/vo/SyncDatasourceVO.java
new file mode 100644
index 0000000000..385b8a94ee
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/datasource/vo/SyncDatasourceVO.java
@@ -0,0 +1,57 @@
+package io.dataease.api.sync.datasource.vo;
+
+import lombok.Data;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/20 11:18
+ **/
+@Data
+public class SyncDatasourceVO {
+ /**
+ * ID
+ */
+ private String id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 描述
+ */
+ private String desc;
+
+ /**
+ * 类型
+ */
+ private String type;
+
+ /**
+ * 详细信息
+ */
+ private String configuration;
+
+ /**
+ * Create timestamp
+ */
+ private Long createTime;
+
+ /**
+ * Update timestamp
+ */
+ private Long updateTime;
+
+ /**
+ * 创建人
+ */
+ private Long createBy;
+ private String createByName;
+
+ /**
+ * 状态
+ */
+ private String status;
+ private String statusRemark;
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/summary/api/SummaryApi.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/summary/api/SummaryApi.java
new file mode 100644
index 0000000000..9e83033c18
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/summary/api/SummaryApi.java
@@ -0,0 +1,26 @@
+package io.dataease.api.sync.summary.api;
+
+import io.dataease.auth.DeApiPath;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.Map;
+
+import static io.dataease.constant.AuthResourceEnum.SUMMARY;
+
+/**
+ * @author fit2cloud
+ * @date 2023/12/4 12:43
+ **/
+@DeApiPath(value = "/sync/summary", rt = SUMMARY)
+public interface SummaryApi {
+
+ @GetMapping("/resourceCount")
+ Map resourceCount();
+
+ @PostMapping("/logChartData")
+ Map logChartData(@RequestBody String executeTaskLogDate);
+
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskApi.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskApi.java
new file mode 100644
index 0000000000..f272b1a919
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskApi.java
@@ -0,0 +1,52 @@
+package io.dataease.api.sync.task.api;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.dataease.api.sync.task.dto.TaskInfoDTO;
+import io.dataease.api.sync.task.vo.TaskInfoVO;
+import io.dataease.auth.DeApiPath;
+import io.dataease.exception.DEException;
+import io.dataease.request.BaseGridRequest;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static io.dataease.constant.AuthResourceEnum.TASK;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/20 10:14
+ **/
+@DeApiPath(value = "/sync/task", rt = TASK)
+public interface TaskApi {
+
+ @PostMapping("/pager/{goPage}/{pageSize}")
+ IPage pager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
+
+ @PostMapping("/add")
+ void add(@RequestBody TaskInfoDTO jobInfo) throws DEException;
+
+ @PostMapping("/update")
+ void update(@RequestBody TaskInfoDTO jobInfo) throws DEException;
+
+ @DeleteMapping("/remove/{id}")
+ void remove(@PathVariable(value = "id") String id) throws DEException;
+
+ @GetMapping("start/{id}")
+ void startJob(@PathVariable(value = "id") String id) throws DEException;
+
+ @GetMapping("stop/{id}")
+ void stopJob(@PathVariable(value = "id") String id) throws DEException;
+
+ @GetMapping("/get/{id}")
+ TaskInfoVO getOneById(@PathVariable(value = "id") String id) throws DEException;
+
+ @GetMapping("/execute/{id}")
+ void execute(@PathVariable(value = "id") String id) throws DEException;
+
+ @PostMapping("/batch/del")
+ void batchDelete(@RequestBody List ids) throws DEException;
+
+ @GetMapping("/count")
+ Long count() throws DEException;
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskLogApi.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskLogApi.java
new file mode 100644
index 0000000000..925eec1254
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/api/TaskLogApi.java
@@ -0,0 +1,39 @@
+package io.dataease.api.sync.task.api;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.dataease.api.sync.task.vo.LogResultVO;
+import io.dataease.api.sync.task.vo.TaskLogVO;
+import io.dataease.auth.DeApiPath;
+import io.dataease.request.BaseGridRequest;
+import org.springframework.web.bind.annotation.*;
+
+import static io.dataease.constant.AuthResourceEnum.TASK_LOG;
+
+/**
+ * @author fit2cloud
+ * @date 2023/12/4 12:43
+ **/
+@DeApiPath(value = "/sync/task/log", rt = TASK_LOG)
+public interface TaskLogApi {
+ @PostMapping("/pager/{goPage}/{pageSize}")
+ IPage pager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
+
+ @GetMapping("/detail/{logId}/{fromLineNum}")
+ LogResultVO logDetail(@PathVariable("logId") String logId, @PathVariable("fromLineNum") int fromLineNum);
+
+ @PostMapping("/save")
+ void saveLog(@RequestBody TaskLogVO logDetail);
+
+ @PostMapping("/update")
+ void updateLog(@RequestBody TaskLogVO logDetail);
+
+ @DeleteMapping("/deleteByJobId/{jobId}")
+ void deleteByJobId(@PathVariable("jobId") String jobId);
+
+ @DeleteMapping("/delete/{logId}")
+ void deleteById(@PathVariable("logId") String logId);
+
+ @PostMapping("/clear")
+ void clearJobLog(@RequestBody TaskLogVO taskLogVO);
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Source.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Source.java
new file mode 100644
index 0000000000..6c7c908c17
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Source.java
@@ -0,0 +1,23 @@
+package io.dataease.api.sync.task.dto;
+
+import io.dataease.api.sync.datasource.dto.SyncDatasourceDTO;
+import lombok.Data;
+
+import java.util.List;
+
+
+/**
+ * @author fit2cloud
+ * @date 2023/8/10 16:38
+ **/
+@Data
+public class Source {
+ private String type;
+ private String query;
+ private String tables;
+ private SyncDatasourceDTO datasource;
+ private String datasourceId;
+ private String tableExtract;
+ private List fieldList;
+ private String incrementField;
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TableField.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TableField.java
new file mode 100644
index 0000000000..ec6b79d07b
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TableField.java
@@ -0,0 +1,22 @@
+package io.dataease.api.sync.task.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author fit2cloud
+ */
+@Setter
+@Getter
+public class TableField {
+ private String fieldSource;
+ private String fieldName;
+ private String remarks;
+ private String fieldType;
+ private int fieldSize;
+ private boolean fieldPk;
+ private boolean fieldIndex;
+ private int accuracy;
+ private Object defaultValue;
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Target.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Target.java
new file mode 100644
index 0000000000..66ab74ea5d
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/Target.java
@@ -0,0 +1,21 @@
+package io.dataease.api.sync.task.dto;
+
+import io.dataease.api.sync.datasource.dto.SyncDatasourceDTO;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author fit2cloud
+ * @date 2023/8/10 16:39
+ **/
+@Data
+public class Target {
+ private String type;
+ private String createTable;
+ private List fieldList;
+ private String tableName;
+ private SyncDatasourceDTO datasource;
+ private String datasourceId;
+ private String targetProperty;
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TaskInfoDTO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TaskInfoDTO.java
new file mode 100644
index 0000000000..03c05a7869
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/dto/TaskInfoDTO.java
@@ -0,0 +1,112 @@
+package io.dataease.api.sync.task.dto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/28 17:17
+ **/
+@Data
+public class TaskInfoDTO {
+ private String id;
+
+ private String name;
+
+ /**
+ * 任务类型KEY
+ */
+ private String jobKey;
+
+ private String desc;
+
+ private LocalDateTime createTime;
+
+ private LocalDateTime modifyTime;
+
+ /**
+ * 创建人
+ */
+ private Long createBy;
+
+ /**
+ * 修改人
+ */
+ private Long modifyBy;
+
+ /**
+ * 任务参数
+ */
+ private String parameter;
+
+ /**
+ * 扩展参数
+ */
+ private String extParameter;
+
+ /**
+ * 当前任务状态
+ * unexecuted未执行 currentTime=currentTime>=startTime,status=1
+ * suspend暂停 stopTime>=currentTime>=startTime,status=0
+ * done执行结束 currentTime>stopTime
+ * running执行中,通过当前任务的日志状态判断,如果有日志在执行中
+ */
+ private String status;
+
+ /**
+ * 删除标识
+ */
+ private Boolean deleted;
+
+ /**
+ * 任务执行超时时间
+ */
+ private Long executorTimeout;
+
+ /**
+ * 任务执行失败重试次数
+ */
+ private Long executorFailRetryCount;
+
+ /**
+ * 上次调度时间
+ */
+ private Long triggerLastTime;
+
+ /**
+ * 下次次调度时间
+ */
+ private Long triggerNextTime;
+
+ /**
+ * 调度类型,NONE,CRON,FIX_RATE,FIX_DELAY
+ */
+ private String schedulerType;
+
+ /**
+ * 调度配置,取决于调度类型
+ */
+ private String schedulerConf;
+
+ /**
+ * 开始时间
+ */
+ private String startTime;
+
+ /**
+ * 结束时间
+ */
+ private String stopTime;
+
+
+ /**
+ * 源数据源信息
+ */
+ private Source source;
+ /**
+ * 目标数据源信息
+ */
+ private Target target;
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/LogResultVO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/LogResultVO.java
new file mode 100644
index 0000000000..58d62e9ee0
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/LogResultVO.java
@@ -0,0 +1,46 @@
+package io.dataease.api.sync.task.vo;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 日志返回结果
+ *
+ * @author fit2cloud
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+public class LogResultVO implements Serializable{
+
+ /**
+ * 日志开始行号
+ */
+ private int fromLineNum;
+ /**
+ * 日志结束行号
+ */
+ private int toLineNum;
+ /**
+ * 日志内容
+ */
+ private String logContent;
+ /**
+ * 是否是最后一行
+ */
+ private boolean isEnd;
+
+ public LogResultVO(int fromLineNum, int toLineNum, String logContent, boolean isEnd) {
+ this.fromLineNum = fromLineNum;
+ this.toLineNum = toLineNum;
+ this.logContent = logContent;
+ this.isEnd = isEnd;
+ }
+
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskInfoVO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskInfoVO.java
new file mode 100644
index 0000000000..e814ac3fd5
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskInfoVO.java
@@ -0,0 +1,132 @@
+package io.dataease.api.sync.task.vo;
+
+import io.dataease.api.sync.task.dto.Source;
+import io.dataease.api.sync.task.dto.Target;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author fit2cloud
+ * @date 2023/11/28 17:15
+ **/
+@Data
+public class TaskInfoVO {
+
+ private String id;
+
+ private String name;
+
+ /**
+ * 任务类型KEY
+ */
+ private String jobKey;
+
+ private String desc;
+
+ private LocalDateTime createTime;
+
+ private LocalDateTime modifyTime;
+
+ /**
+ * 创建人
+ */
+ private Long createBy;;
+ /**
+ * 创建人
+ */
+ private String userName;
+
+ /**
+ * 任务参数
+ */
+ private String parameter;
+
+ /**
+ * 扩展参数
+ */
+ private String extParameter;
+
+ /**
+ * 任务状态
+ * unexecuted未执行 currentTime=currentTime>=startTime,status=1
+ * suspend暂停 stopTime>=currentTime>=startTime,status=0
+ * done执行结束 currentTime>stopTime
+ * running执行中,通过当前任务的日志状态判断,如果有日志在执行中
+ */
+ private String status;
+
+ /**
+ * 删除标识
+ */
+ private Boolean deleted;
+
+ /**
+ * 任务执行超时时间
+ */
+ private Long executorTimeout;
+
+ /**
+ * 任务执行失败重试次数
+ */
+ private Long executorFailRetryCount;
+
+ /**
+ * 上次调度时间
+ */
+ private Long triggerLastTime;
+
+ /**
+ * 下次次调度时间
+ */
+ private Long triggerNextTime;
+
+ /**
+ * 调度类型,NONE,CRON,FIX_RATE,FIX_DELAY
+ */
+ private String schedulerType;
+
+ /**
+ * 调度配置,取决于调度类型
+ */
+ private String schedulerConf;
+
+ /**
+ * 开始时间
+ */
+ private Long startTime;
+
+ /**
+ * 结束时间
+ */
+ private Long stopTime;
+
+ private Source source;
+ private Target target;
+
+ /**
+ * 上次执行结果,获取任务最新的日志状态
+ * running执行中
+ * success
+ * fail失败
+ */
+ private String lastExecuteStatus;
+ private Long incrementValue;
+
+ // 以下为日志信息
+ private String logId;
+ private Long executorStartTime;
+ private Long executorEndTime;
+ private String executorMsg;
+ /**
+ * 成功SUCCESS,失败FAIL,执行中RUNNING
+ */
+ private String logStatus;
+
+ /**
+ * 在执行周期内
+ */
+ private boolean withinCycle;
+
+}
diff --git a/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskLogVO.java b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskLogVO.java
new file mode 100644
index 0000000000..44289bc91a
--- /dev/null
+++ b/sdk/api/api-sync/src/main/java/io/dataease/api/sync/task/vo/TaskLogVO.java
@@ -0,0 +1,25 @@
+package io.dataease.api.sync.task.vo;
+
+import lombok.Data;
+
+/**
+ * 任务日志
+ * @author fit2cloud
+ * @date 2023/9/19 17:44
+ **/
+@Data
+public class TaskLogVO {
+
+ private String id;
+ private String jobId;
+ private String jobName;
+ private String jobDesc;
+ private Long executorStartTime;
+ private Long executorEndTime;
+ private String status;
+ private String executorMsg;
+ private String executorAddress;
+
+ private String clearType;
+
+}
diff --git a/sdk/api/pom.xml b/sdk/api/pom.xml
index 58186de6bd..d9f8c90c22 100644
--- a/sdk/api/pom.xml
+++ b/sdk/api/pom.xml
@@ -15,6 +15,7 @@
api-permissions
api-base
+ api-sync
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 093f3835ad..60270644d1 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);
+ 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(10, 8), TASK(11, 9),TASK_LOG(12, 10), SUMMARY(13, 11);
private long menuId;