MdpSyncTaskConfigService.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. using Admin.NET.Plugin.AiDOP.Dto.DataPlatform;
  2. using Admin.NET.Plugin.AiDOP.Entity.DataPlatform;
  3. using Admin.NET.Plugin.AiDOP.Order;
  4. namespace Admin.NET.Plugin.AiDOP.DataPlatform;
  5. /// <summary>
  6. /// 数据中台同步配置中心 API。
  7. /// </summary>
  8. [ApiDescriptionSettings(Order = 323, Description = "数据中台同步配置中心")]
  9. [Route("api/DataPlatform")]
  10. [AllowAnonymous]
  11. [NonUnify]
  12. public class MdpSyncTaskConfigService : IDynamicApiController, ITransient
  13. {
  14. private static readonly HashSet<string> ProtectedTaskCodes = new(StringComparer.OrdinalIgnoreCase)
  15. {
  16. "S1_MDP_SYNC_TRANSFORM",
  17. "S2_MDP_SYNC_TRANSFORM",
  18. "S3_MDP_SYNC_TRANSFORM",
  19. "S4_MDP_SYNC_TRANSFORM"
  20. };
  21. private readonly ISqlSugarClient _db;
  22. private readonly UserManager _userManager;
  23. public MdpSyncTaskConfigService(ISqlSugarClient db, UserManager userManager)
  24. {
  25. _db = db;
  26. _userManager = userManager;
  27. }
  28. [DisplayName("同步任务列表")]
  29. [HttpGet("sync-tasks")]
  30. public async Task<object> GetList([FromQuery] MdpSyncTaskListQuery input)
  31. {
  32. var tenantId = _userManager.TenantId;
  33. var page = input.Page <= 0 ? 1 : input.Page;
  34. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  35. var offset = (page - 1) * pageSize;
  36. var where = new List<string> { "(t.tenant_id = @TenantId OR t.tenant_id = 0)", "t.status = 1" };
  37. var pars = new List<SugarParameter> { new("@TenantId", tenantId) };
  38. if (!string.IsNullOrWhiteSpace(input.Keyword))
  39. {
  40. where.Add("(t.task_code LIKE @Keyword OR t.task_name LIKE @Keyword OR t.business_domain_name LIKE @Keyword)");
  41. pars.Add(new SugarParameter("@Keyword", $"%{input.Keyword.Trim()}%"));
  42. }
  43. if (!string.IsNullOrWhiteSpace(input.BusinessDomainCode))
  44. {
  45. where.Add("t.business_domain_code = @BusinessDomainCode");
  46. pars.Add(new SugarParameter("@BusinessDomainCode", input.BusinessDomainCode.Trim()));
  47. }
  48. if (input.Status.HasValue)
  49. {
  50. where[1] = "t.status = @Status";
  51. pars.Add(new SugarParameter("@Status", input.Status.Value));
  52. }
  53. var whereSql = string.Join(" AND ", where);
  54. var total = await _db.Ado.GetIntAsync($"SELECT COUNT(1) FROM mdp_sync_task t WHERE {whereSql}", pars);
  55. var list = await _db.Ado.SqlQueryAsync<MdpSyncTaskListRow>(
  56. $"""
  57. SELECT t.id AS Id, t.tenant_id AS TenantId, t.task_code AS TaskCode, t.task_name AS TaskName,
  58. t.task_type AS TaskType, t.business_domain_code AS BusinessDomainCode,
  59. t.business_domain_name AS BusinessDomainName, t.consumer_modules AS ConsumerModules,
  60. t.source_system_code AS SourceSystemCode, t.service_key AS ServiceKey,
  61. t.job_code AS JobCode, t.schedule_job_id AS ScheduleJobId, t.status AS Status,
  62. t.config_version AS ConfigVersion, t.description AS Description,
  63. sch.schedule_mode AS ScheduleMode,
  64. IFNULL(sch.auto_enabled, 1) AS AutoEnabled,
  65. IFNULL(sch.manual_enabled, 1) AS ManualEnabled,
  66. run.status AS LastRunStatus, run.start_time AS LastRunTime
  67. FROM mdp_sync_task t
  68. LEFT JOIN mdp_sync_task_schedule sch
  69. ON sch.tenant_id = t.tenant_id AND sch.task_code = t.task_code
  70. LEFT JOIN (
  71. SELECT job_code, MAX(start_time) AS last_run_time
  72. FROM mdp_transform_run_log
  73. WHERE {MdpMonitorService.BuildMdpRunLogTenantWhere(tenantId)}
  74. GROUP BY job_code
  75. ) latest ON latest.job_code = IFNULL(t.job_code, t.task_code)
  76. LEFT JOIN mdp_transform_run_log run
  77. ON run.job_code = latest.job_code AND run.start_time = latest.last_run_time
  78. WHERE {whereSql}
  79. ORDER BY t.task_code
  80. LIMIT {pageSize} OFFSET {offset}
  81. """,
  82. pars);
  83. return new { total, page, pageSize, list };
  84. }
  85. [DisplayName("同步任务详情")]
  86. [HttpGet("sync-tasks/{id:long}")]
  87. public async Task<object> GetDetail(long id)
  88. {
  89. var tenantId = _userManager.TenantId;
  90. var row = await _db.Ado.SqlQuerySingleAsync<MdpSyncTaskListRow>(
  91. $"""
  92. SELECT t.id AS Id, t.tenant_id AS TenantId, t.task_code AS TaskCode, t.task_name AS TaskName,
  93. t.task_type AS TaskType, t.business_domain_code AS BusinessDomainCode,
  94. t.business_domain_name AS BusinessDomainName, t.consumer_modules AS ConsumerModules,
  95. t.source_system_code AS SourceSystemCode, t.service_key AS ServiceKey,
  96. t.job_code AS JobCode, t.schedule_job_id AS ScheduleJobId, t.status AS Status,
  97. t.config_version AS ConfigVersion, t.description AS Description,
  98. sch.schedule_mode AS ScheduleMode,
  99. IFNULL(sch.auto_enabled, 1) AS AutoEnabled,
  100. IFNULL(sch.manual_enabled, 1) AS ManualEnabled,
  101. run.status AS LastRunStatus, run.start_time AS LastRunTime
  102. FROM mdp_sync_task t
  103. LEFT JOIN mdp_sync_task_schedule sch
  104. ON sch.tenant_id = t.tenant_id AND sch.task_code = t.task_code
  105. LEFT JOIN (
  106. SELECT job_code, MAX(start_time) AS last_run_time
  107. FROM mdp_transform_run_log
  108. WHERE {MdpMonitorService.BuildMdpRunLogTenantWhere(tenantId)}
  109. GROUP BY job_code
  110. ) latest ON latest.job_code = IFNULL(t.job_code, t.task_code)
  111. LEFT JOIN mdp_transform_run_log run
  112. ON run.job_code = latest.job_code AND run.start_time = latest.last_run_time
  113. WHERE t.id = @Id AND (t.tenant_id = @TenantId OR t.tenant_id = 0)
  114. LIMIT 1
  115. """,
  116. new SugarParameter("@Id", id),
  117. new SugarParameter("@TenantId", tenantId));
  118. if (row == null)
  119. throw Oops.Oh("同步任务不存在");
  120. return row;
  121. }
  122. [DisplayName("新增同步任务")]
  123. [HttpPost("sync-tasks")]
  124. public async Task<object> Create([FromBody] MdpSyncTaskUpsertInput input)
  125. {
  126. ValidateUpsert(input);
  127. var tenantId = _userManager.TenantId;
  128. var exists = await _db.Queryable<MdpSyncTask>()
  129. .Where(u => u.TenantId == tenantId && u.TaskCode == input.TaskCode.Trim())
  130. .AnyAsync();
  131. if (exists)
  132. throw Oops.Oh("任务编码已存在");
  133. var entity = MapUpsert(input, tenantId);
  134. entity.ConfigVersion = 1;
  135. entity.CreateTime = DateTime.Now;
  136. entity.UpdateTime = DateTime.Now;
  137. var id = await _db.Insertable(entity).ExecuteReturnBigIdentityAsync();
  138. await EnsureDefaultScheduleAsync(tenantId, entity.TaskCode, entity.ScheduleJobId);
  139. return new { id };
  140. }
  141. [DisplayName("更新同步任务")]
  142. [HttpPut("sync-tasks/{id:long}")]
  143. public async Task<object> Update(long id, [FromBody] MdpSyncTaskUpsertInput input)
  144. {
  145. ValidateUpsert(input);
  146. var tenantId = _userManager.TenantId;
  147. var entity = await FindEditableTaskAsync(id, tenantId);
  148. entity.TaskName = input.TaskName.Trim();
  149. entity.TaskType = string.IsNullOrWhiteSpace(input.TaskType) ? "SERVICE_SYNC" : input.TaskType.Trim();
  150. entity.BusinessDomainCode = input.BusinessDomainCode?.Trim();
  151. entity.BusinessDomainName = input.BusinessDomainName?.Trim();
  152. entity.ConsumerModules = input.ConsumerModules?.Trim();
  153. entity.SourceSystemCode = input.SourceSystemCode?.Trim();
  154. entity.ServiceKey = input.ServiceKey?.Trim();
  155. entity.JobCode = string.IsNullOrWhiteSpace(input.JobCode) ? input.TaskCode.Trim() : input.JobCode.Trim();
  156. entity.ScheduleJobId = input.ScheduleJobId?.Trim();
  157. entity.Status = input.Status <= 0 ? 0 : 1;
  158. entity.OwnerRole = input.OwnerRole?.Trim();
  159. entity.Description = input.Description?.Trim();
  160. entity.ConfigVersion += 1;
  161. entity.UpdateTime = DateTime.Now;
  162. if (!ProtectedTaskCodes.Contains(entity.TaskCode))
  163. entity.TaskCode = input.TaskCode.Trim();
  164. await _db.Updateable(entity).ExecuteCommandAsync();
  165. await SyncScheduleJobIdAsync(entity.TenantId, entity.TaskCode, entity.ScheduleJobId);
  166. return new { id = entity.Id };
  167. }
  168. [DisplayName("删除同步任务")]
  169. [HttpDelete("sync-tasks/{id:long}")]
  170. public async Task<object> Delete(long id)
  171. {
  172. var tenantId = _userManager.TenantId;
  173. var entity = await FindEditableTaskAsync(id, tenantId);
  174. if (ProtectedTaskCodes.Contains(entity.TaskCode) && entity.TenantId == 0)
  175. throw Oops.Oh("内置 MDP 同步任务不允许删除");
  176. entity.Status = 0;
  177. entity.UpdateTime = DateTime.Now;
  178. await _db.Updateable(entity).UpdateColumns(u => new { u.Status, u.UpdateTime }).ExecuteCommandAsync();
  179. return new { id };
  180. }
  181. [DisplayName("同步任务步骤列表")]
  182. [HttpGet("sync-tasks/{taskCode}/steps")]
  183. public async Task<object> GetSteps(string taskCode)
  184. {
  185. var tenantId = _userManager.TenantId;
  186. await EnsureTaskExistsAsync(taskCode, tenantId);
  187. var steps = await _db.Queryable<MdpSyncTaskStep>()
  188. .Where(u => u.TaskCode == taskCode && (u.TenantId == tenantId || u.TenantId == 0))
  189. .OrderBy(u => u.SortOrder)
  190. .ToListAsync();
  191. return steps.Select(MapStepRow).ToList();
  192. }
  193. [DisplayName("保存同步任务步骤")]
  194. [HttpPut("sync-tasks/{taskCode}/steps")]
  195. public async Task<object> SaveSteps(string taskCode, [FromBody] List<MdpSyncTaskStepRow> input)
  196. {
  197. var tenantId = _userManager.TenantId;
  198. var task = await EnsureTaskExistsAsync(taskCode, tenantId);
  199. var rows = input ?? new List<MdpSyncTaskStepRow>();
  200. var now = DateTime.Now;
  201. foreach (var row in rows)
  202. {
  203. if (string.IsNullOrWhiteSpace(row.StepCode) || string.IsNullOrWhiteSpace(row.StepName))
  204. throw Oops.Oh("步骤编码和名称不能为空");
  205. var entity = await _db.Queryable<MdpSyncTaskStep>()
  206. .Where(u => u.TaskCode == taskCode && u.StepCode == row.StepCode && (u.TenantId == tenantId || u.TenantId == 0))
  207. .FirstAsync();
  208. if (entity == null)
  209. {
  210. entity = new MdpSyncTaskStep
  211. {
  212. TenantId = task.TenantId == 0 ? 0 : tenantId,
  213. TaskCode = taskCode,
  214. StepCode = row.StepCode.Trim(),
  215. StepName = row.StepName.Trim(),
  216. StageType = string.IsNullOrWhiteSpace(row.StageType) ? row.StepCode.Trim() : row.StageType.Trim(),
  217. ServiceMethodKey = row.ServiceMethodKey?.Trim(),
  218. Enabled = row.Enabled ? 1 : 0,
  219. SortOrder = row.SortOrder,
  220. Description = row.Description?.Trim(),
  221. CreateTime = now,
  222. UpdateTime = now
  223. };
  224. await _db.Insertable(entity).ExecuteCommandAsync();
  225. }
  226. else
  227. {
  228. entity.StepName = row.StepName.Trim();
  229. entity.StageType = string.IsNullOrWhiteSpace(row.StageType) ? row.StepCode.Trim() : row.StageType.Trim();
  230. entity.ServiceMethodKey = row.ServiceMethodKey?.Trim();
  231. entity.Enabled = row.Enabled ? 1 : 0;
  232. entity.SortOrder = row.SortOrder;
  233. entity.Description = row.Description?.Trim();
  234. entity.UpdateTime = now;
  235. await _db.Updateable(entity).ExecuteCommandAsync();
  236. }
  237. }
  238. task.ConfigVersion += 1;
  239. task.UpdateTime = now;
  240. await _db.Updateable(task).UpdateColumns(u => new { u.ConfigVersion, u.UpdateTime }).ExecuteCommandAsync();
  241. return new { count = rows.Count };
  242. }
  243. [DisplayName("同步任务调度配置")]
  244. [HttpGet("sync-tasks/{taskCode}/schedule")]
  245. public async Task<object> GetSchedule(string taskCode)
  246. {
  247. var tenantId = _userManager.TenantId;
  248. await EnsureTaskExistsAsync(taskCode, tenantId);
  249. var schedule = await FindScheduleAsync(taskCode, tenantId);
  250. if (schedule == null)
  251. return new MdpSyncTaskScheduleRow { TaskCode = taskCode, ScheduleMode = "CRON" };
  252. return MapScheduleRow(schedule);
  253. }
  254. [DisplayName("保存同步任务调度配置")]
  255. [HttpPut("sync-tasks/{taskCode}/schedule")]
  256. public async Task<object> SaveSchedule(string taskCode, [FromBody] MdpSyncTaskScheduleRow input)
  257. {
  258. var tenantId = _userManager.TenantId;
  259. var task = await EnsureTaskExistsAsync(taskCode, tenantId);
  260. var schedule = await FindScheduleAsync(taskCode, tenantId);
  261. var now = DateTime.Now;
  262. if (schedule == null)
  263. {
  264. schedule = new MdpSyncTaskSchedule
  265. {
  266. TenantId = task.TenantId == 0 ? 0 : tenantId,
  267. TaskCode = taskCode,
  268. CreateTime = now,
  269. UpdateTime = now
  270. };
  271. }
  272. schedule.ScheduleJobId = input.ScheduleJobId?.Trim() ?? task.ScheduleJobId;
  273. schedule.ScheduleMode = string.IsNullOrWhiteSpace(input.ScheduleMode) ? "CRON" : input.ScheduleMode.Trim();
  274. schedule.CronExpr = input.CronExpr?.Trim();
  275. schedule.CronDesc = input.CronDesc?.Trim();
  276. schedule.Timezone = string.IsNullOrWhiteSpace(input.Timezone) ? "Asia/Shanghai" : input.Timezone.Trim();
  277. schedule.AutoEnabled = input.AutoEnabled ? 1 : 0;
  278. schedule.ManualEnabled = input.ManualEnabled ? 1 : 0;
  279. schedule.RetryEnabled = input.RetryEnabled ? 1 : 0;
  280. schedule.MaxRetryCount = input.MaxRetryCount <= 0 ? 3 : input.MaxRetryCount;
  281. schedule.RetryIntervalSeconds = input.RetryIntervalSeconds <= 0 ? 300 : input.RetryIntervalSeconds;
  282. schedule.TimeoutSeconds = input.TimeoutSeconds <= 0 ? 3600 : input.TimeoutSeconds;
  283. schedule.MisfirePolicy = input.MisfirePolicy?.Trim();
  284. schedule.SyncWindowType = string.IsNullOrWhiteSpace(input.SyncWindowType) ? "FULL" : input.SyncWindowType.Trim();
  285. schedule.SyncWindowValue = input.SyncWindowValue?.Trim();
  286. schedule.LastScheduleTime = input.LastScheduleTime;
  287. schedule.NextScheduleTime = input.NextScheduleTime;
  288. schedule.AdminJobConfigJson = input.AdminJobConfigJson;
  289. schedule.Description = input.Description?.Trim();
  290. schedule.UpdateTime = now;
  291. if (schedule.Id <= 0)
  292. await _db.Insertable(schedule).ExecuteCommandAsync();
  293. else
  294. await _db.Updateable(schedule).ExecuteCommandAsync();
  295. task.ScheduleJobId = schedule.ScheduleJobId;
  296. task.ConfigVersion += 1;
  297. task.UpdateTime = now;
  298. await _db.Updateable(task).UpdateColumns(u => new { u.ScheduleJobId, u.ConfigVersion, u.UpdateTime }).ExecuteCommandAsync();
  299. return MapScheduleRow(schedule);
  300. }
  301. [DisplayName("同步 Admin.NET 调度快照")]
  302. [HttpPost("sync-tasks/{taskCode}/schedule/sync-admin-job")]
  303. public async Task<object> SyncAdminJob(string taskCode)
  304. {
  305. var tenantId = _userManager.TenantId;
  306. var task = await EnsureTaskExistsAsync(taskCode, tenantId);
  307. var schedule = await FindScheduleAsync(taskCode, tenantId) ?? new MdpSyncTaskSchedule
  308. {
  309. TenantId = task.TenantId == 0 ? 0 : tenantId,
  310. TaskCode = taskCode,
  311. ScheduleJobId = task.ScheduleJobId,
  312. ScheduleMode = "CRON",
  313. CreateTime = DateTime.Now,
  314. UpdateTime = DateTime.Now
  315. };
  316. schedule.AdminJobConfigJson = System.Text.Json.JsonSerializer.Serialize(new
  317. {
  318. scheduleJobId = schedule.ScheduleJobId ?? task.ScheduleJobId,
  319. message = "第一阶段仅保存 Admin.NET Job 绑定快照,不写回底层 Cron 配置。"
  320. });
  321. schedule.UpdateTime = DateTime.Now;
  322. if (schedule.Id <= 0)
  323. await _db.Insertable(schedule).ExecuteCommandAsync();
  324. else
  325. await _db.Updateable(schedule).UpdateColumns(u => new { u.AdminJobConfigJson, u.UpdateTime }).ExecuteCommandAsync();
  326. return new
  327. {
  328. taskCode,
  329. scheduleJobId = schedule.ScheduleJobId ?? task.ScheduleJobId,
  330. adminJobConfigJson = schedule.AdminJobConfigJson
  331. };
  332. }
  333. private async Task<MdpSyncTask> EnsureTaskExistsAsync(string taskCode, long tenantId)
  334. {
  335. if (string.IsNullOrWhiteSpace(taskCode))
  336. throw Oops.Oh("任务编码不能为空");
  337. var task = await _db.Queryable<MdpSyncTask>()
  338. .Where(u => u.TaskCode == taskCode && (u.TenantId == tenantId || u.TenantId == 0) && u.Status == 1)
  339. .OrderBy(u => u.TenantId, OrderByType.Desc)
  340. .FirstAsync();
  341. if (task == null)
  342. throw Oops.Oh("同步任务不存在");
  343. return task;
  344. }
  345. private async Task<MdpSyncTask> FindEditableTaskAsync(long id, long tenantId)
  346. {
  347. var entity = await _db.Queryable<MdpSyncTask>()
  348. .Where(u => u.Id == id && (u.TenantId == tenantId || u.TenantId == 0))
  349. .FirstAsync();
  350. if (entity == null)
  351. throw Oops.Oh("同步任务不存在");
  352. return entity;
  353. }
  354. private async Task<MdpSyncTaskSchedule?> FindScheduleAsync(string taskCode, long tenantId) =>
  355. await _db.Queryable<MdpSyncTaskSchedule>()
  356. .Where(u => u.TaskCode == taskCode && (u.TenantId == tenantId || u.TenantId == 0))
  357. .OrderBy(u => u.TenantId, OrderByType.Desc)
  358. .FirstAsync();
  359. private async Task EnsureDefaultScheduleAsync(long tenantId, string taskCode, string? scheduleJobId)
  360. {
  361. var exists = await _db.Queryable<MdpSyncTaskSchedule>()
  362. .Where(u => u.TaskCode == taskCode && (u.TenantId == tenantId || u.TenantId == 0))
  363. .AnyAsync();
  364. if (exists)
  365. return;
  366. await _db.Insertable(new MdpSyncTaskSchedule
  367. {
  368. TenantId = tenantId,
  369. TaskCode = taskCode,
  370. ScheduleJobId = scheduleJobId,
  371. ScheduleMode = "CRON",
  372. CronDesc = "按 Admin.NET 任务调度执行",
  373. AutoEnabled = 1,
  374. ManualEnabled = 1,
  375. RetryEnabled = 1,
  376. MaxRetryCount = 3,
  377. RetryIntervalSeconds = 300,
  378. TimeoutSeconds = 3600,
  379. SyncWindowType = "FULL",
  380. CreateTime = DateTime.Now,
  381. UpdateTime = DateTime.Now
  382. }).ExecuteCommandAsync();
  383. }
  384. private async Task SyncScheduleJobIdAsync(long tenantId, string taskCode, string? scheduleJobId)
  385. {
  386. var schedule = await FindScheduleAsync(taskCode, tenantId);
  387. if (schedule == null)
  388. {
  389. await EnsureDefaultScheduleAsync(tenantId, taskCode, scheduleJobId);
  390. return;
  391. }
  392. schedule.ScheduleJobId = scheduleJobId;
  393. schedule.UpdateTime = DateTime.Now;
  394. await _db.Updateable(schedule).UpdateColumns(u => new { u.ScheduleJobId, u.UpdateTime }).ExecuteCommandAsync();
  395. }
  396. private static void ValidateUpsert(MdpSyncTaskUpsertInput input)
  397. {
  398. if (string.IsNullOrWhiteSpace(input.TaskCode))
  399. throw Oops.Oh("任务编码不能为空");
  400. if (string.IsNullOrWhiteSpace(input.TaskName))
  401. throw Oops.Oh("任务名称不能为空");
  402. }
  403. private static MdpSyncTask MapUpsert(MdpSyncTaskUpsertInput input, long tenantId) =>
  404. new()
  405. {
  406. TenantId = tenantId,
  407. TaskCode = input.TaskCode.Trim(),
  408. TaskName = input.TaskName.Trim(),
  409. TaskType = string.IsNullOrWhiteSpace(input.TaskType) ? "SERVICE_SYNC" : input.TaskType.Trim(),
  410. BusinessDomainCode = input.BusinessDomainCode?.Trim(),
  411. BusinessDomainName = input.BusinessDomainName?.Trim(),
  412. ConsumerModules = input.ConsumerModules?.Trim(),
  413. SourceSystemCode = input.SourceSystemCode?.Trim(),
  414. ServiceKey = input.ServiceKey?.Trim(),
  415. JobCode = string.IsNullOrWhiteSpace(input.JobCode) ? input.TaskCode.Trim() : input.JobCode.Trim(),
  416. ScheduleJobId = input.ScheduleJobId?.Trim(),
  417. Status = input.Status <= 0 ? 0 : 1,
  418. OwnerRole = input.OwnerRole?.Trim(),
  419. Description = input.Description?.Trim()
  420. };
  421. private static MdpSyncTaskStepRow MapStepRow(MdpSyncTaskStep step) =>
  422. new()
  423. {
  424. Id = step.Id,
  425. StepCode = step.StepCode,
  426. StepName = step.StepName,
  427. StageType = step.StageType,
  428. ServiceMethodKey = step.ServiceMethodKey,
  429. Enabled = step.Enabled != 0,
  430. SortOrder = step.SortOrder,
  431. Description = step.Description
  432. };
  433. private static MdpSyncTaskScheduleRow MapScheduleRow(MdpSyncTaskSchedule schedule) =>
  434. new()
  435. {
  436. TaskCode = schedule.TaskCode,
  437. ScheduleJobId = schedule.ScheduleJobId,
  438. ScheduleMode = schedule.ScheduleMode,
  439. CronExpr = schedule.CronExpr,
  440. CronDesc = schedule.CronDesc,
  441. Timezone = schedule.Timezone,
  442. AutoEnabled = schedule.AutoEnabled != 0,
  443. ManualEnabled = schedule.ManualEnabled != 0,
  444. RetryEnabled = schedule.RetryEnabled != 0,
  445. MaxRetryCount = schedule.MaxRetryCount,
  446. RetryIntervalSeconds = schedule.RetryIntervalSeconds,
  447. TimeoutSeconds = schedule.TimeoutSeconds,
  448. MisfirePolicy = schedule.MisfirePolicy,
  449. SyncWindowType = schedule.SyncWindowType,
  450. SyncWindowValue = schedule.SyncWindowValue,
  451. LastScheduleTime = schedule.LastScheduleTime,
  452. NextScheduleTime = schedule.NextScheduleTime,
  453. AdminJobConfigJson = schedule.AdminJobConfigJson,
  454. Description = schedule.Description
  455. };
  456. }