forked from github/dataease
Merge pull request #7574 from dataease/pr@dev-v2@sync-task
feat(系统管理-同步管理):
This commit is contained in:
commit
a42660c315
@ -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
|
||||
|
47
core/core-frontend/src/api/sync/syncDatasource.ts
Normal file
47
core/core-frontend/src/api/sync/syncDatasource.ts
Normal file
@ -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 })
|
||||
}
|
26
core/core-frontend/src/api/sync/syncSummary.ts
Normal file
26
core/core-frontend/src/api/sync/syncSummary.ts
Normal file
@ -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: ''
|
||||
})
|
||||
}
|
224
core/core-frontend/src/api/sync/syncTask.ts
Normal file
224
core/core-frontend/src/api/sync/syncTask.ts
Normal file
@ -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}` })
|
||||
}
|
20
core/core-frontend/src/api/sync/syncTaskLog.ts
Normal file
20
core/core-frontend/src/api/sync/syncTaskLog.ts
Normal file
@ -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 })
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.95219 8.73169L15.5501 3.13376C15.7128 2.97104 15.9767 2.97104 16.1394 3.13376L16.7286 3.72301C16.8913 3.88573 16.8913 4.14955 16.7286 4.31227L11.1307 9.9102L16.7286 15.5081C16.8913 15.6708 16.8913 15.9347 16.7286 16.0974L16.1394 16.6866C15.9767 16.8494 15.7128 16.8494 15.5501 16.6866L9.95219 11.0887L4.35426 16.6866C4.19154 16.8494 3.92772 16.8494 3.76501 16.6866L3.17575 16.0974C3.01303 15.9347 3.01303 15.6708 3.17575 15.5081L8.77368 9.9102L3.17575 4.31227C3.01303 4.14955 3.01303 3.88573 3.17575 3.72301L3.76501 3.13376C3.92772 2.97104 4.19154 2.97104 4.35426 3.13376L9.95219 8.73169Z" fill="#646A73"/>
|
||||
</svg>
|
After Width: | Height: | Size: 724 B |
16
core/core-frontend/src/assets/svg/icon_sync_datasource.svg
Normal file
16
core/core-frontend/src/assets/svg/icon_sync_datasource.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_10054_936)">
|
||||
<path d="M0 6.66667C0 2.98477 3.25611 0 7.27273 0H32.7273C36.7439 0 40 2.98477 40 6.66667V33.3333C40 37.0152 36.7439 40 32.7273 40H7.27273C3.25611 40 0 37.0152 0 33.3333V6.66667Z" fill="#EBF1FF"/>
|
||||
<g clip-path="url(#clip1_10054_936)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.9019 28.8369C30.5346 28.3383 31.1111 27.6133 31.1111 26.6667V13.3334C31.1111 12.3868 30.5346 11.6618 29.9019 11.1632C29.2567 10.6547 28.392 10.2454 27.4225 9.92225C25.4718 9.27202 22.8476 8.88892 20 8.88892C17.1524 8.88892 14.5283 9.27202 12.5776 9.92225C11.6081 10.2454 10.7433 10.6547 10.0981 11.1632C9.46546 11.6618 8.88892 12.3868 8.88892 13.3334V26.6667C8.88892 27.6133 9.46546 28.3383 10.0981 28.8369C10.7433 29.3453 11.6081 29.7546 12.5776 30.0778C14.5283 30.728 17.1524 31.1111 20 31.1111C22.8476 31.1111 25.4718 30.728 27.4225 30.0778C28.392 29.7546 29.2567 29.3453 29.9019 28.8369ZM11.1111 13.3331C11.1118 12.1059 15.0912 11.1111 20 11.1111C24.9092 11.1111 28.8889 12.1061 28.8889 13.3334C28.8889 14.5607 24.9092 15.5556 20 15.5556C15.0908 15.5556 11.1111 14.5607 11.1111 13.3334C11.1111 13.3333 11.1111 13.3333 11.1111 13.3333C11.1111 13.3332 11.1111 13.3331 11.1111 13.3331ZM27.4225 16.7445C27.9482 16.5692 28.4431 16.3687 28.8889 16.1407V20.0003C28.8889 20.0016 28.8888 20.0064 28.8855 20.017C28.8818 20.0294 28.8724 20.0539 28.8499 20.0905C28.8028 20.1673 28.7066 20.2828 28.5264 20.4248C28.1596 20.714 27.5598 21.0229 26.7197 21.303C25.0511 21.8592 22.6753 22.2222 20 22.2222C17.3248 22.2222 14.9489 21.8592 13.2803 21.303C12.4402 21.0229 11.8405 20.714 11.4736 20.4248C11.2934 20.2828 11.1973 20.1673 11.1501 20.0905C11.1276 20.0539 11.1183 20.0294 11.1145 20.017C11.1113 20.0065 11.1111 20.0014 11.1111 20V16.1407C11.5569 16.3687 12.0519 16.5692 12.5776 16.7445C14.5283 17.3947 17.1524 17.7778 20 17.7778C22.8476 17.7778 25.4718 17.3947 27.4225 16.7445ZM27.4225 23.4111C27.9482 23.2359 28.4431 23.0353 28.8889 22.8074V26.6668C28.8889 26.6678 28.8889 26.6725 28.8855 26.6837C28.8818 26.6961 28.8724 26.7205 28.8499 26.7572C28.8028 26.834 28.7066 26.9495 28.5264 27.0915C28.1596 27.3806 27.5598 27.6896 26.7197 27.9696C25.0511 28.5258 22.6753 28.8889 20 28.8889C17.3248 28.8889 14.9489 28.5258 13.2803 27.9696C12.4402 27.6896 11.8405 27.3806 11.4736 27.0915C11.2934 26.9495 11.1973 26.834 11.1501 26.7572C11.1276 26.7205 11.1183 26.6961 11.1145 26.6837C11.1111 26.6725 11.1111 26.6677 11.1111 26.6667V22.8074C11.5569 23.0353 12.0519 23.2359 12.5776 23.4111C14.5283 24.0614 17.1524 24.4445 20 24.4445C22.8476 24.4445 25.4718 24.0614 27.4225 23.4111Z" fill="#3370FF"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10054_936">
|
||||
<rect width="40" height="40" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_10054_936">
|
||||
<rect width="26.6667" height="26.6667" fill="white" transform="translate(6.66675 6.66669)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
17
core/core-frontend/src/assets/svg/icon_sync_log_number.svg
Normal file
17
core/core-frontend/src/assets/svg/icon_sync_log_number.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_10054_2080)">
|
||||
<path d="M0 6.66667C0 2.98477 3.25611 0 7.27273 0H32.7273C36.7439 0 40 2.98477 40 6.66667V33.3333C40 37.0152 36.7439 40 32.7273 40H7.27273C3.25611 40 0 37.0152 0 33.3333V6.66667Z" fill="#E5FBF8"/>
|
||||
<g clip-path="url(#clip1_10054_2080)">
|
||||
<path d="M18.0958 25.682L25.7858 20.8437C25.928 20.7535 26.0452 20.6289 26.1264 20.4814C26.2075 20.3339 26.2501 20.1682 26.2501 19.9998C26.2501 19.8315 26.2075 19.6658 26.1264 19.5183C26.0452 19.3707 25.928 19.2461 25.7858 19.156L18.0962 14.318C17.9388 14.219 17.7575 14.1667 17.5722 14.1667C17.4419 14.1671 17.3131 14.1932 17.1929 14.2434C17.0728 14.2937 16.9637 14.3671 16.8719 14.4595C16.7801 14.5519 16.7075 14.6614 16.658 14.7819C16.6086 14.9024 16.5834 15.0314 16.5838 15.1617V24.8387C16.5839 25.0248 16.636 25.2072 16.7342 25.3653C16.8024 25.4759 16.8919 25.5719 16.9974 25.6478C17.1029 25.7236 17.2225 25.7778 17.349 25.8073C17.4756 25.8367 17.6068 25.8408 17.7349 25.8193C17.8631 25.7978 17.9858 25.7511 18.0958 25.682Z" fill="#00D6B9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.9998 7.77771C26.7498 7.77771 32.222 13.2499 32.222 19.9999C32.222 26.7499 26.7498 32.2222 19.9998 32.2222C13.2498 32.2222 7.77759 26.7499 7.77759 19.9999C7.77759 13.2499 13.2498 7.77771 19.9998 7.77771ZM19.9998 9.44438C25.8293 9.44438 30.5554 14.1704 30.5554 19.9999C30.5554 25.8295 25.8293 30.5555 19.9998 30.5555C14.1703 30.5555 9.44425 25.8295 9.44425 19.9999C9.44425 14.1704 14.1703 9.44438 19.9998 9.44438Z" fill="#00D6B9"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10054_2080">
|
||||
<rect width="40" height="40" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_10054_2080">
|
||||
<rect width="26.6667" height="26.6667" fill="white" transform="translate(6.66675 6.66669)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,3 @@
|
||||
<svg width="12" height="16" viewBox="0 0 12 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.66667 2.00033H1.33333V14.0003H10.6667V4.01333H9C8.91159 4.01333 8.82681 3.97821 8.7643 3.91569C8.70179 3.85318 8.66667 3.7684 8.66667 3.67999V2.00033ZM0.666667 0.666992H9.39033C9.47793 0.666967 9.56467 0.684205 9.64561 0.717722C9.72654 0.751238 9.80007 0.800376 9.862 0.862326L11.805 2.80599C11.9299 2.93104 12.0001 3.10058 12 3.27733V14.667C12 14.8438 11.9298 15.0134 11.8047 15.1384C11.6797 15.2634 11.5101 15.3337 11.3333 15.3337H0.666667C0.489856 15.3337 0.320286 15.2634 0.195262 15.1384C0.0702379 15.0134 4.14401e-09 14.8438 0 14.667V1.33366C4.14401e-09 1.15685 0.0702379 0.987279 0.195262 0.862254C0.320286 0.73723 0.489856 0.666992 0.666667 0.666992ZM3.33333 6.66699H8.66667C8.75507 6.66699 8.83986 6.70211 8.90237 6.76462C8.96488 6.82714 9 6.91192 9 7.00033V7.66699C9 7.7554 8.96488 7.84018 8.90237 7.90269C8.83986 7.96521 8.75507 8.00033 8.66667 8.00033H3.33333C3.24493 8.00033 3.16014 7.96521 3.09763 7.90269C3.03512 7.84018 3 7.7554 3 7.66699V7.00033C3 6.91192 3.03512 6.82714 3.09763 6.76462C3.16014 6.70211 3.24493 6.66699 3.33333 6.66699ZM3.33333 10.0003H6.33333C6.37711 10.0003 6.42045 10.0089 6.46089 10.0257C6.50134 10.0424 6.53808 10.067 6.56904 10.098C6.59999 10.1289 6.62454 10.1657 6.64129 10.2061C6.65805 10.2465 6.66667 10.2899 6.66667 10.3337V11.0003C6.66667 11.0441 6.65805 11.0874 6.64129 11.1279C6.62454 11.1683 6.59999 11.2051 6.56904 11.236C6.53808 11.267 6.50134 11.2915 6.46089 11.3083C6.42045 11.325 6.37711 11.3337 6.33333 11.3337H3.33333C3.24493 11.3337 3.16014 11.2985 3.09763 11.236C3.03512 11.1735 3 11.0887 3 11.0003V10.3337C3 10.2453 3.03512 10.1605 3.09763 10.098C3.16014 10.0354 3.24493 10.0003 3.33333 10.0003Z" fill="#3370FF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="14" viewBox="0 0 16 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.66666 12.0002H5.66666C2.90523 12.0002 0.666656 9.76164 0.666656 7.00022C0.666656 5.02373 1.81347 3.3151 3.47799 2.50343L4.14705 3.66228C2.8804 4.23986 1.99999 5.51723 1.99999 7.00022C1.99999 9.02526 3.64161 10.6669 5.66666 10.6669H8.66666V9.77154C8.66666 9.57824 8.82336 9.42154 9.01666 9.42154C9.10143 9.42154 9.18333 9.45231 9.24713 9.50814L11.0323 11.0702C11.1778 11.1974 11.1925 11.4186 11.0652 11.564C11.055 11.5757 11.044 11.5867 11.0323 11.597L9.24713 13.159C9.10166 13.2863 8.88054 13.2715 8.75325 13.126C8.69743 13.0622 8.66666 12.9803 8.66666 12.8956V12.0002ZM7.33333 3.33356V4.22891C7.33333 4.31369 7.30256 4.39559 7.24673 4.45939C7.11944 4.60486 6.89832 4.6196 6.75285 4.49231L4.96769 2.9303C4.956 2.92007 4.945 2.90907 4.93477 2.89737C4.80748 2.7519 4.82222 2.53078 4.96769 2.4035L6.75285 0.841481C6.81665 0.785654 6.89855 0.754883 6.98333 0.754883C7.17663 0.754883 7.33333 0.911583 7.33333 1.10488V2.00023H10.3333C13.0947 2.00023 15.3333 4.23881 15.3333 7.00023C15.3333 8.96233 14.2031 10.6605 12.5583 11.4791L11.8897 10.3212C13.1366 9.73578 14 8.46883 14 7.00023C14 4.97519 12.3584 3.33356 10.3333 3.33356H7.33333Z" fill="#3370FF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
17
core/core-frontend/src/assets/svg/icon_sync_task_number.svg
Normal file
17
core/core-frontend/src/assets/svg/icon_sync_task_number.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_7277_272394)">
|
||||
<path d="M0 6.66667C0 2.98477 3.25611 0 7.27273 0H32.7273C36.7439 0 40 2.98477 40 6.66667V33.3333C40 37.0152 36.7439 40 32.7273 40H7.27273C3.25611 40 0 37.0152 0 33.3333V6.66667Z" fill="#FFF3E5"/>
|
||||
<g clip-path="url(#clip1_7277_272394)">
|
||||
<path d="M14.7474 21.6382C14.7785 21.7131 14.824 21.7812 14.8814 21.8385L18.3726 25.3304L18.4311 25.3822C18.6733 25.5696 19.0237 25.5526 19.2459 25.3304L25.3563 19.2193C25.472 19.1035 25.537 18.9466 25.537 18.783C25.537 18.6193 25.472 18.4624 25.3563 18.3467L24.4837 17.4733C24.4264 17.4159 24.3583 17.3704 24.2834 17.3393C24.2084 17.3082 24.1281 17.2923 24.047 17.2923C23.9659 17.2923 23.8856 17.3082 23.8106 17.3393C23.7357 17.3704 23.6676 17.4159 23.6103 17.4733L18.8096 22.2748L16.6266 20.0926C16.5109 19.9769 16.354 19.9119 16.1903 19.9119C16.0267 19.9119 15.8697 19.9769 15.754 20.0926L14.8814 20.9652C14.824 21.0225 14.7785 21.0906 14.7474 21.1655C14.7164 21.2404 14.7004 21.3207 14.7004 21.4019C14.7004 21.483 14.7164 21.5633 14.7474 21.6382Z" fill="#FF8800"/>
|
||||
<path d="M24.4442 7.77777H15.5553C14.8739 7.77777 14.4442 8.2074 14.4442 8.88888V9.99999H11.1111C10.3489 9.99999 10 10.4296 10 11.1111V31.1111C10 31.7933 10.3489 32.2222 11.1111 32.2222L28.8889 32.2222C29.6511 32.2222 30 31.7926 30 31.1111V11.1111C30 10.4289 29.6511 9.99996 28.8889 9.99996L25.5556 9.99999V12.2222H27.7778V30H12.2222V12.2222H14.4442V13.3333C14.4442 14.0148 14.8739 14.4444 15.5553 14.4444H24.4442C25.1257 14.4444 25.5553 14.0148 25.5553 13.3333V8.88888C25.5553 8.20666 25.1257 7.77777 24.4442 7.77777ZM16.6664 12.2222V9.99999H23.3331V12.2222H16.6664Z" fill="#FF8800"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_7277_272394">
|
||||
<rect width="40" height="40" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_7277_272394">
|
||||
<rect width="26.6667" height="26.6667" fill="white" transform="translate(6.66675 6.66669)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -1,46 +1,66 @@
|
||||
<script setup lang="ts">
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { ElSelect, ElPopover, ElOption, ElIcon } from 'element-plus-secondary'
|
||||
import { computed, reactive, nextTick, ref } from 'vue'
|
||||
import { Icon } from '@/components/icon-custom'
|
||||
import { computed, PropType, reactive, toRefs } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
interface Config {
|
||||
// 显示类型
|
||||
showType: string
|
||||
// 日期分隔符
|
||||
rangeSeparator: string
|
||||
// 前缀图标
|
||||
prefixIcon: string
|
||||
// 开始日期label
|
||||
startPlaceholder: string
|
||||
// 结束日期label
|
||||
endPlaceholder: string
|
||||
// 日期格式
|
||||
format: string
|
||||
// 日期值格式
|
||||
valueFormat: string
|
||||
// 尺寸
|
||||
size: string
|
||||
// 弹出位置
|
||||
placement: string
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
statusList: propTypes.arrayOf(
|
||||
propTypes.shape({
|
||||
id: propTypes.string,
|
||||
name: propTypes.string
|
||||
})
|
||||
),
|
||||
property: Object as PropType<Config>,
|
||||
title: propTypes.string
|
||||
})
|
||||
|
||||
const { property } = toRefs(props)
|
||||
const timeConfig = computed(() => {
|
||||
let obj = Object.assign(
|
||||
{
|
||||
showType: 'datetime',
|
||||
rangeSeparator: '-',
|
||||
prefixIcon: 'Calendar',
|
||||
startPlaceholder: t('datasource.start_time'),
|
||||
endPlaceholder: t('datasource.end_time'),
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
size: 'default',
|
||||
placement: 'bottom-end'
|
||||
},
|
||||
property.value
|
||||
)
|
||||
return obj
|
||||
})
|
||||
const state = reactive({
|
||||
currentStatus: [],
|
||||
activeStatus: []
|
||||
modelValue: []
|
||||
})
|
||||
|
||||
const elPopoverU = ref(null)
|
||||
const more = ref(null)
|
||||
|
||||
const statusChange = (id: string | number) => {
|
||||
state.activeStatus = state.activeStatus.filter(ele => ele.id !== id)
|
||||
const emits = defineEmits(['filter-change'])
|
||||
const onChange = () => {
|
||||
emits('filter-change', state.modelValue)
|
||||
}
|
||||
const selectStatus = ids => {
|
||||
const [item] = ids
|
||||
state.activeStatus.push(item)
|
||||
state.currentStatus = []
|
||||
nextTick(() => {
|
||||
elPopoverU.value.hide()
|
||||
more.value.click()
|
||||
})
|
||||
const clear = () => {
|
||||
state.modelValue = []
|
||||
}
|
||||
|
||||
const statusListNotSelect = computed(() => {
|
||||
return props.statusList.filter(ele => !state.activeStatus.map(t => t.id).includes(ele.id))
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
activeStatus: state.activeStatus
|
||||
clear
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -48,108 +68,42 @@ defineExpose({
|
||||
<div class="filter">
|
||||
<span>{{ title }}</span>
|
||||
<div class="filter-item">
|
||||
<span
|
||||
v-for="ele in state.activeStatus"
|
||||
:key="ele.id"
|
||||
class="item active"
|
||||
@click="statusChange(ele.id)"
|
||||
>{{ $t(ele.name) }}</span
|
||||
>
|
||||
<slot v-if="!!statusListNotSelect.length">
|
||||
<el-popover
|
||||
:show-arrow="false"
|
||||
ref="elPopoverU"
|
||||
placement="bottom"
|
||||
popper-class="filter-popper"
|
||||
width="200"
|
||||
trigger="click"
|
||||
>
|
||||
<el-select
|
||||
:teleported="false"
|
||||
style="width: 100%"
|
||||
v-model="state.currentStatus"
|
||||
value-key="id"
|
||||
filterable
|
||||
multiple
|
||||
@change="selectStatus"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in statusListNotSelect"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<template #reference>
|
||||
<span ref="more" class="more">
|
||||
<el-icon>
|
||||
<Icon name="icon_add_outlined"> </Icon>
|
||||
</el-icon>
|
||||
更多
|
||||
</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</slot>
|
||||
<el-date-picker
|
||||
v-model="state.modelValue"
|
||||
:type="timeConfig.showType"
|
||||
:range-separator="timeConfig.rangeSeparator"
|
||||
:prefix-icon="timeConfig.prefixIcon"
|
||||
:start-placeholder="timeConfig.startPlaceholder"
|
||||
:end-placeholder="timeConfig.endPlaceholder"
|
||||
:format="timeConfig.format"
|
||||
:value-format="timeConfig.valueFormat"
|
||||
key="drawer-time-filt"
|
||||
:size="timeConfig.size"
|
||||
@change="onChange"
|
||||
:placement="timeConfig.placement"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scope>
|
||||
.filter {
|
||||
display: flex;
|
||||
min-height: 46px;
|
||||
min-height: 32px;
|
||||
|
||||
> :nth-child(1) {
|
||||
color: var(--deTextSecondary, #1f2329);
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
|
||||
font-family: 'PingFang SC';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
white-space: nowrap;
|
||||
width: 116px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
|
||||
.item,
|
||||
.more {
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
margin-right: 12px;
|
||||
text-align: center;
|
||||
padding: 1px 6px;
|
||||
background: var(--deTextPrimary5, #f5f6f7);
|
||||
color: var(--deTextPrimary, #1f2329);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.active,
|
||||
.more:hover {
|
||||
background: var(--primary10, rgba(51, 112, 255, 0.1));
|
||||
color: var(--primaryselect, #0c296e);
|
||||
}
|
||||
|
||||
.more {
|
||||
white-space: nowrap;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.filter-popper {
|
||||
padding: 0 !important;
|
||||
background: #fff !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -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)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -2132,6 +2132,57 @@ export default {
|
||||
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: '查看日志'
|
||||
},
|
||||
watermark: {
|
||||
support_params: '当前支持的参数:',
|
||||
enable: '启用水印',
|
||||
|
20
sdk/api/api-sync/pom.xml
Normal file
20
sdk/api/api-sync/pom.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>api</artifactId>
|
||||
<groupId>io.dataease</groupId>
|
||||
<version>${dataease.version}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>api-sync</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -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<SyncDatasourceVO> sourcePager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
|
||||
|
||||
@DePermit("m:read")
|
||||
@PostMapping("/target/pager/{goPage}/{pageSize}")
|
||||
IPage<SyncDatasourceVO> 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<String> getSchema(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
|
||||
|
||||
@DePermit({"#p0+':manage'"})
|
||||
@GetMapping("/validate/{datasourceId}")
|
||||
SyncDatasourceDTO validate(@PathVariable("datasourceId") String datasourceId) throws DEException;
|
||||
|
||||
@PostMapping("/latestUse")
|
||||
List<String> latestUse();
|
||||
|
||||
@GetMapping("/get/{datasourceId}")
|
||||
SyncDatasourceDTO get(@PathVariable("datasourceId") String datasourceId) throws DEException;
|
||||
|
||||
@PostMapping("/batchDel")
|
||||
void batchDel(@RequestBody List<String> ids) throws DEException;
|
||||
|
||||
@PostMapping("/fields")
|
||||
Map<String, Object> getFields(@RequestBody GetDatasourceRequest getDsRequest) throws DEException ;
|
||||
|
||||
@GetMapping("/list/{type}")
|
||||
List<SyncDatasourceDTO> listByType(@PathVariable("type") String type) throws DEException;
|
||||
|
||||
@GetMapping("/table/list/{dsId}")
|
||||
List<DBTableDTO> getTableList(@PathVariable("dsId") String dsId) throws DEException;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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<String, Long> resourceCount();
|
||||
|
||||
@PostMapping("/logChartData")
|
||||
Map<String, Object> logChartData(@RequestBody String executeTaskLogDate);
|
||||
|
||||
|
||||
}
|
@ -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<TaskInfoVO> 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<String> ids) throws DEException;
|
||||
|
||||
@GetMapping("/count")
|
||||
Long count() throws DEException;
|
||||
|
||||
}
|
@ -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<TaskLogVO> 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);
|
||||
|
||||
}
|
@ -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<TableField> fieldList;
|
||||
private String incrementField;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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<TableField> fieldList;
|
||||
private String tableName;
|
||||
private SyncDatasourceDTO datasource;
|
||||
private String datasourceId;
|
||||
private String targetProperty;
|
||||
}
|
@ -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<startTime
|
||||
* waiting等待执行 stopTime>=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;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package io.dataease.api.sync.task.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 日志返回结果
|
||||
*
|
||||
* @author fit2cloud
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class LogResultVO {
|
||||
|
||||
/**
|
||||
* 日志开始行号
|
||||
*/
|
||||
private int fromLineNum;
|
||||
/**
|
||||
* 日志结束行号
|
||||
*/
|
||||
private int toLineNum;
|
||||
/**
|
||||
* 日志内容
|
||||
*/
|
||||
private String logContent;
|
||||
/**
|
||||
* 是否是最后一行
|
||||
*/
|
||||
private boolean isEnd;
|
||||
|
||||
public LogResultVO() {
|
||||
|
||||
}
|
||||
|
||||
public LogResultVO(int fromLineNum, int toLineNum, String logContent, boolean isEnd) {
|
||||
this.fromLineNum = fromLineNum;
|
||||
this.toLineNum = toLineNum;
|
||||
this.logContent = logContent;
|
||||
this.isEnd = isEnd;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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<startTime
|
||||
* waiting等待执行 stopTime>=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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
<modules>
|
||||
<module>api-permissions</module>
|
||||
<module>api-base</module>
|
||||
<module>api-sync</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user