Explorar el Código

Merge branch 'dev' of http://123.60.180.165:4647/ZZYDOP/DOPCore into dev

tangdi hace 2 años
padre
commit
422bfc3eb5
Se han modificado 100 ficheros con 6762 adiciones y 14 borrados
  1. 25 0
      MicroServices/Business/Business.Application.Contracts/Dto/MonthlyCapacityDto.cs
  2. 24 0
      MicroServices/Business/Business.Application.Contracts/Dto/ProdLineDto.cs
  3. 1 1
      MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs
  4. 168 10
      MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs
  5. 1 1
      MicroServices/Business/Business.Domain/StructuredDB/MES/IC/LocationDetail.cs
  6. 1 1
      MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/MonthlyProdCapacity.cs
  7. 57 0
      MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/MonthlyProdCapacityDtl.cs
  8. 44 0
      MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/SkuVersionSet.cs
  9. 68 0
      MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/crm_planorder.cs
  10. 1 1
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/BusinessDbContextModelCreatingExtensions.cs
  11. 15 0
      MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs
  12. 11 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Attributes/NoLoginAttribute.cs
  13. 10 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/AppConfig.cs
  14. 16 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/AppSetting.cs
  15. 13 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/BaseResult.cs
  16. 63 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Constant.cs
  17. 57 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/EncryptDecryptExtension.cs
  18. 11 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/ConnectionMethod.cs
  19. 12 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/JobTypeEnum.cs
  20. 9 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/MailMessageEnum.cs
  21. 16 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/RequestTypeEnum.cs
  22. 14 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/TriggerTypeEnum.cs
  23. 80 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/FileConfig.cs
  24. 182 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/HttpHelper.cs
  25. 61 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/MailHelper.cs
  26. 16 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Common/StringExtension.cs
  27. 219 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Controllers/JobController.cs
  28. 208 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Controllers/SetingController.cs
  29. 23 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Dockerfile
  30. 21 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Dockerfile[树莓派]
  31. 90 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/JobBriefInfoEntity.cs
  32. 116 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/JobInfoEntity.cs
  33. 12 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/LoginInfoEntity.cs
  34. 12 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/LoginInfoOutput.cs
  35. 27 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/MailEntity.cs
  36. 13 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/ModifyJobInput.cs
  37. 15 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/MqttOptionsEntity.cs
  38. 15 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/RabbitOptionsEntity.cs
  39. 15 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/RefreshIntervalEntity.cs
  40. 93 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/ScheduleEntity.cs
  41. 13 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/UpdateLoginInfoEntity.cs
  42. 1 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/File/LoginPassword.json
  43. 1 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/File/RefreshInterval.json
  44. 1 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/File/rabbitmq.json
  45. 55 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Filters/AuthorizationFilter.cs
  46. 94 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Host.csproj
  47. 10 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Host.csproj.user
  48. 83 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/HttpJob.cs
  49. 125 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/JobBase.cs
  50. 28 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/MailJob.cs
  51. 12 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogMailModel.cs
  52. 35 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogModel.cs
  53. 8 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogMqttModel.cs
  54. 8 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogRabbitModel.cs
  55. 18 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogUrlModel.cs
  56. 46 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/MqttJob.cs
  57. 47 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/RabbitJob.cs
  58. 103 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/MqttManager.cs
  59. 62 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/RabbitMQManager.cs
  60. 617 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/SchedulerCenter.cs
  61. 17 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Model/HttpResultModel.cs
  62. 44 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Model/LogInfoModel.cs
  63. 11 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Model/SendMailModel.cs
  64. 20 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Program.cs
  65. 19 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/PublishProfiles/FolderProfile.pubxml
  66. 11 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/PublishProfiles/FolderProfile.pubxml.user
  67. 12 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/launchSettings.json
  68. 17 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/IRepositorie.cs
  69. 241 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/OracleDynamicParameters.cs
  70. 37 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieFactory.cs
  71. 87 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieMySql.cs
  72. 59 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieOracle.cs
  73. 88 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositoriePostgreSQL.cs
  74. 90 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieSQLite.cs
  75. 87 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieSqlServer.cs
  76. 25 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/ScheduleManage.cs
  77. 35 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Services/HostedService.cs
  78. 180 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Startup.cs
  79. 174 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_firebird.sql
  80. 179 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_mysql_innodb.sql
  81. 194 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_oracle.sql
  82. 169 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_postgres.sql
  83. 364 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlServer.sql
  84. 381 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlServerMOT.sql
  85. 181 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlite.sql
  86. 10 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/appsettings.Development.json
  87. 43 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/appsettings.json
  88. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/1-es2015.f3b9d43ee6db9fa820da.js
  89. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/1-es5.f3b9d43ee6db9fa820da.js
  90. 529 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/3rdpartylicenses.txt
  91. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/6-es2015.a4e363a7248c7daffe8a.js
  92. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/6-es5.a4e363a7248c7daffe8a.js
  93. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/7-es2015.bfb7deef134855a4f9fd.js
  94. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/7-es5.bfb7deef134855a4f9fd.js
  95. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/8-es2015.a1b00527ed656e5e5a76.js
  96. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/8-es5.a1b00527ed656e5e5a76.js
  97. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/9-es2015.8365ef5288043f903909.js
  98. 0 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/9-es5.8365ef5288043f903909.js
  99. 118 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/assets/i18n/en.json
  100. 118 0
      MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/assets/i18n/zh.json

+ 25 - 0
MicroServices/Business/Business.Application.Contracts/Dto/MonthlyCapacityDto.cs

@@ -0,0 +1,25 @@
+using Business.Domain;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    /// <summary>
+    /// 月度产能共识Dto
+    /// </summary>
+    public class MonthlyCapacityDto
+    {
+        /// <summary>
+        /// 月度产能共识主表
+        /// </summary>
+        public List<MonthlyProdCapacity> mains { get; set; }
+
+        /// <summary>
+        /// 月度产能共识明细表
+        /// </summary>
+        public List<MonthlyProdCapacityDtl> details { get; set; }
+    }
+}

+ 24 - 0
MicroServices/Business/Business.Application.Contracts/Dto/ProdLineDto.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    /// <summary>
+    /// 产线明细Dto
+    /// </summary>
+    public class ProdLineDto
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string Part { get; set; }
+
+        /// <summary>
+        /// 产线
+        /// </summary>
+        public string Line { get; set; }
+    }
+}

+ 1 - 1
MicroServices/Business/Business.Application/ResourceExamineManagement/ResourceExamineAppService.cs

@@ -1738,7 +1738,7 @@ namespace Business.ResourceExamineManagement
                     item.bang_id = bangid;
                     var pret = pretreatments.Find(s => s.item_id == item.icitem_id);
                     if(pret != null) {
-                        item.sqty = locStock.Where(s => s.ItemNum == pret.item_number).Sum(p => p.QtyOnHand.GetValueOrDefault());
+                        item.sqty = locStock.Where(s => s.ItemNum == pret.item_number).Sum(p => p.QtyOnHand);
                     }
                 });
                 var moIcitemStokc = ObjectMapper.Map<List<ic_item_stock>, List<mo_ic_item_stock>>(icitemStokc);

+ 168 - 10
MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs

@@ -12,6 +12,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Threading.Tasks;
+using ThoughtWorks.QRCode.Geom;
 using Volo.Abp.Application.Services;
 using Volo.Abp.DependencyInjection;
 using Volo.Abp.Domain.Repositories;
@@ -112,6 +113,21 @@ namespace Business.SaleForecastManagement
         /// </summary>
         private IRepository<MonthlyProdCapacity, long> _monthlyProdCapacity;
 
+        /// <summary>
+        /// 月度产能共识明细表
+        /// </summary>
+        private IRepository<MonthlyProdCapacityDtl, long> _monthlyProdCapacityDtl;
+
+        /// <summary>
+        /// SKU版本维护表
+        /// </summary>
+        private IRepository<SkuVersionSet, long> _skuVersionSet;
+
+        /// <summary>
+        /// 计划订单表
+        /// </summary>
+        private IRepository<crm_planorder, long> _crm_planorder;
+
         /// <summary>
         /// 雪花算法
         /// </summary>
@@ -139,7 +155,10 @@ namespace Business.SaleForecastManagement
             IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
             ISqlRepository<LocationDetail> locationDetail,
             ISqlRepository<WorkOrdMaster> workOrdMaster,
-            IRepository<OverallDemandPlan, long> overallDemandPlan
+            IRepository<OverallDemandPlan, long> overallDemandPlan,
+            IRepository<MonthlyProdCapacityDtl, long> monthlyProdCapacityDtl,
+            IRepository<SkuVersionSet, long> skuVersionSet,
+            IRepository<crm_planorder, long> crm_planorder
             )
         {
             _ic_item = ic_item;
@@ -159,6 +178,9 @@ namespace Business.SaleForecastManagement
             _locationDetail = locationDetail;
             _workOrdMaster = workOrdMaster;
             _overallDemandPlan = overallDemandPlan;
+            _monthlyProdCapacityDtl = monthlyProdCapacityDtl;
+            _skuVersionSet= skuVersionSet;
+            _crm_planorder= crm_planorder;
         }
         #endregion
 
@@ -397,7 +419,12 @@ namespace Business.SaleForecastManagement
             #endregion
 
             //生成月度产能共识
-            List<MonthlyProdCapacity> capacities = CapacityAnalysis(input, updates, planMons);
+            var capacityDto = CapacityAnalysis(input, updates, planMons);
+
+            //生成下一个月的补货计划
+            var nextMonPFcsts = platformFcsts.Where(p => p.PlanMonth == strN2).ToList();
+            var nextMonDFcsts = domesticFcst.Where(p => p.PlanMonth == strN2).ToList();
+            var replenishs = MonthlyReplenish(input, nextMonPFcsts, nextMonDFcsts, standards, items, holidays);
 
             //保存数据
             using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
@@ -421,9 +448,14 @@ namespace Business.SaleForecastManagement
                     }
                     //回写年度生产大纲
                     await _yearDemandManagement.UpdateManyAsync(updates);
-                    //先删除产能共识
+                    //先删除产能共识、产能共识明细
                     await _monthlyProdCapacity.HardDeleteAsync(p=>p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
-                    await _monthlyProdCapacity.InsertManyAsync(capacities);
+                    await _monthlyProdCapacityDtl.HardDeleteAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
+                    await _monthlyProdCapacity.InsertManyAsync(capacityDto.mains);
+                    await _monthlyProdCapacityDtl.InsertManyAsync(capacityDto.details);
+                    //生成下一月的补货计划
+                    await _crm_planorder.HardDeleteAsync(p=>p.PlanMonth == strN1 && p.Source =="系统运算" && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
+                    await _crm_planorder.InsertManyAsync(replenishs);
 
                     await unitOfWork.CompleteAsync();
                 }
@@ -442,7 +474,7 @@ namespace Business.SaleForecastManagement
         /// </summary>
         /// <param name="input"></param>
         /// <returns></returns>
-        public List<MonthlyProdCapacity> CapacityAnalysis(InputDto input,List<YearDemandManagement> yearDemands, List<string> planMons)
+        public MonthlyCapacityDto CapacityAnalysis(InputDto input,List<YearDemandManagement> yearDemands, List<string> planMons)
         {
             //1、获取数据
             //1.1 根据规格型号获取物料数据
@@ -458,6 +490,9 @@ namespace Business.SaleForecastManagement
 
             //月度产能共识表
             List<MonthlyProdCapacity> capacities = new List<MonthlyProdCapacity>();
+            //月度产能共识明细表
+            List<MonthlyProdCapacityDtl> capacityDtls = new List<MonthlyProdCapacityDtl>();
+
             //产线
             List<string> lines = lineDtls.Select(p => p.Line).Distinct().ToList();
             foreach (var item in lines)
@@ -489,10 +524,46 @@ namespace Business.SaleForecastManagement
                     dtl.AvailableTimes = dtl.DailyWorks * dtl.MonthWorks;
                     //计算产线耗时
                     var curLines = lineDtls.Where(p => p.Line == item).ToList();
-                    var line = curLines.OrderByDescending(p => p.Op).First();
-                    var curStands = standards.Where(p=> curLines.Select(m=>m.Part).Contains(p.ItemNumber)).ToList();
-                    var curDemands = yearDemands.Where(p => curStands.Select(m => m.Model).Contains(p.Model) && p.PlanMonth == pm).ToList();
-                    dtl.NeedWorks = line.Rate == 0 ? 0 : (Math.Ceiling(curDemands.Sum(p=>p.Qty) / line.Rate));
+                    decimal sumTimes = 0.00m;
+                    List<ProdLineDto> lineDtos = new List<ProdLineDto>(); 
+                    foreach (var ld in curLines)
+                    {
+                        if (lineDtos.Exists(p=>p.Part == ld.Part && p.Line == ld.Line))
+                        {
+                            continue;
+                        }
+                        var curStand = standards.FirstOrDefault(p => p.ItemNumber == ld.Part);
+                        if (curStand == null)
+                        {
+                            continue;
+                        }
+                        var curDemands = yearDemands.Where(p => p.Model == curStand.Model && p.PlanMonth == pm).ToList();
+                        var line = curLines.Where(p=>p.Part == ld.Part && p.Line == ld.Line).OrderByDescending(p => p.Op).First();
+                        sumTimes += line.Rate == 0 ? 0 : (Math.Ceiling(curDemands.Sum(p => p.Qty) / line.Rate));
+
+                        MonthlyProdCapacityDtl capacityDtl = new MonthlyProdCapacityDtl();
+                        capacityDtl.Year = input.year;
+                        capacityDtl.Month = input.month;
+                        capacityDtl.PlanMonth = pm;
+                        capacityDtl.ProdLine = item;
+                        capacityDtl.Model = curStand.Model;
+                        capacityDtl.Qty = curDemands.Sum(p => p.Qty);
+                        capacityDtl.tenant_id = input.tenant_id;
+                        capacityDtl.company_id = input.company_id;
+                        capacityDtl.factory_id = input.factory_id;
+                        capacityDtl.org_id = input.org_id;
+                        capacityDtl.create_by = input.create_by;
+                        capacityDtl.create_by_name = input.create_by_name;
+                        capacityDtl.create_time = DateTime.Now;
+                        capacityDtls.Add(capacityDtl);
+
+                        lineDtos.Add(new ProdLineDto { 
+                            Part = ld.Part,
+                            Line= ld.Line
+                        });
+                    }
+
+                    dtl.NeedWorks = sumTimes;
                     dtl.ProdRate = 100;
                     dtl.Rate = dtl.AvailableTimes == 0 ? 0 : Math.Floor(dtl.NeedWorks / dtl.AvailableTimes * 100);
                     dtl.IsOverTime = dtl.NeedWorks > dtl.AvailableTimes ? "是" : "否";
@@ -507,9 +578,96 @@ namespace Business.SaleForecastManagement
                     capacities.Add(dtl);
                 }
             }
-            return capacities;
+            return new MonthlyCapacityDto{ 
+                mains = capacities,
+                details = capacityDtls
+            };
+        }
+
+        /// <summary>
+        /// T1、平台自动补货
+        /// </summary>
+        /// <param name="input"></param>
+        /// <param name="platformFcsts">平台预测</param>
+        /// <param name="domesticFcsts">T1预测</param>
+        /// <param name="standards">标准SKU设置</param>
+        /// <param name="items">物料</param>
+        /// <param name="holidays">节假日</param>
+        /// <returns></returns>
+        public List<crm_planorder> MonthlyReplenish(InputDto input, List<PlatformFcstCollect> platformFcsts, List<DomesticTerminalFcst> domesticFcsts, List<StandardItemModelSet> standards, List<ic_item> items, List<HolidayMaster> holidays)
+        { 
+            List<crm_planorder> planorders = new List<crm_planorder>();
+            //获取T1、平台预测数据中规格型号对应的不同版本的物料编码
+            var T1Models = domesticFcsts.Select(p => p.Model).Distinct().ToList();
+            var PModels = platformFcsts.Select(p => p.Model).Distinct().ToList();
+            List<string> models = T1Models;
+            models.AddRange(PModels);
+            models = models.Distinct().ToList();
+            List<SkuVersionSet> skus = _skuVersionSet.GetListAsync(p=>models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
+            //获取库存
+            List<string> itemNums = skus.Select(p=>p.ItemNum).Distinct().ToList();
+            List<LocationDetail> locationDetails = _locationDetail.Select(p=> itemNums.Contains(p.ItemNum) && p.Domain == input.factory_id.ToString() && p.IsActive);
+            //计算T1补货
+            foreach (var item in T1Models)
+            {
+                //获取当前规格型号对应的预测数据
+                var curFcsts = domesticFcsts.Where(p=>p.Model == item).ToList();
+                //当前规格型号对应的库存数量
+                decimal sumQty = 0.00m;
+                //当前的物料版本
+                var curSkus = skus.Where(p => p.Model == item).ToList();
+                if (curSkus.Any())
+                {
+                    sumQty = locationDetails.Where(p => curSkus.Select(p => p.ItemNum).Contains(p.ItemNum)).Sum(p => p.QtyOnHand);
+                }
+                //计算Rop
+                //当前规格型号对应标准SKU的最小包装单位、补货周期
+                var curStd = standards.FirstOrDefault(p => p.Model == item);
+                decimal packQty = 1m;//最小包装单位
+                decimal cycle = 0m;//补货周期
+                if (curStd != null)
+                {
+                    var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
+                    packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
+                    cycle = curStd.ReplenishCycle;
+                }
+                //TODO:获取成品库存、在制库存、灭菌库存,参与计算
+                //N+1月使用N+2月的再订货点参与计算
+                decimal rop = CalcRop(curFcsts[0].PlanMonth + "-01", curFcsts.Sum(p=>p.Qty), packQty, holidays, cycle);
+                if(sumQty < rop)
+                {
+                    planorders.Add(new crm_planorder { 
+                        PlanMonth = curFcsts[0].PlanMonth,
+                        Model = curFcsts[0].Model,
+                        ItemNum = curStd?.ItemNumber,
+                        ProdLine = curFcsts[0].ProdLine,
+                        ProdType = "",
+                        Qty = rop,
+                        Type = "计划单-T1直发补货",
+                        Source = "系统运算",
+                        tenant_id = input.tenant_id,
+                        company_id= input.company_id,
+                        factory_id= input.factory_id,
+                        org_id= input.org_id,
+                        create_by= input.create_by,
+                        create_by_name= input.create_by_name,
+                        create_time = DateTime.Now
+                    });
+                }
+            }
+            //计算平台补货
+            foreach (var item in PModels)
+            {
+
+            }
+
+
+
+
+            return planorders;
         }
 
+
         /// <summary>
         /// 计算再订货点
         /// </summary>

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/MES/IC/LocationDetail.cs

@@ -43,7 +43,7 @@ namespace Business.Domain
         /// 库存数量
         /// </summary>
         [Comment("库存数量")]
-        public decimal? QtyOnHand { get; set; }
+        public decimal QtyOnHand { get; set; }
 
         /// <summary>
         /// 是否有效:1-有效;0-无效

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/MonthlyProdCapacity.cs

@@ -10,7 +10,7 @@ using System.Threading.Tasks;
 namespace Business.Domain
 {
     /// <summary>
-    /// 月度产能共识明细
+    /// 月度产能共识
     /// </summary>
     [Comment("月度产能共识主表")]
     [Index(nameof(Year), nameof(Month),nameof(PlanMonth), nameof(ProdLine), nameof(tenant_id),nameof(company_id), nameof(factory_id), IsUnique = true)]

+ 57 - 0
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/MonthlyProdCapacityDtl.cs

@@ -0,0 +1,57 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+
+namespace Business.Domain
+{
+    /// <summary>
+    /// 月度产能共识明细表
+    /// </summary>
+    [Comment("月度产能共识明细表")]
+    [Index(nameof(Year), nameof(Month),nameof(PlanMonth), nameof(ProdLine),nameof(Model), nameof(tenant_id),nameof(company_id), nameof(factory_id), IsUnique = true)]
+    public class MonthlyProdCapacityDtl:BaseEntity
+    {
+
+        /// <summary>
+        /// 年
+        /// </summary>
+        [Comment("年")]
+        public int? Year { get; set; }
+
+        /// <summary>
+        /// 月
+        /// </summary>
+        [Comment("月")]
+        public int? Month { get; set; }
+
+        /// <summary>
+        /// 计划年月
+        /// </summary>
+        [Comment("计划年月")]
+        public string PlanMonth { get; set; }
+
+        /// <summary>
+        /// 生产线
+        /// </summary>
+        [Comment("生产线")]
+        public string ProdLine { get; set; }
+
+        /// <summary>
+        /// 规格型号
+        /// </summary>
+        [Comment("规格型号")]
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 预估需要生产数量
+        /// </summary>
+        [Comment("预估需要生产数量")]
+        public decimal Qty { get; set; }
+    }
+}

+ 44 - 0
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/SkuVersionSet.cs

@@ -0,0 +1,44 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Domain
+{
+    /// <summary>
+    /// SKU版本号设置表
+    /// </summary>
+    [Comment("SKU版本号设置表")]
+    [Index(nameof(Model),nameof(Language),nameof(ItemNum),nameof(Version), nameof(tenant_id),nameof(company_id), nameof(factory_id), IsUnique = true)]
+    public class SkuVersionSet:BaseEntity
+    {
+        /// <summary>
+        /// 规格型号
+        /// </summary>
+        [Comment("规格型号")]
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 语种
+        /// </summary>
+        [Comment("语种")]
+        public string Language { get; set; }
+
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        [Comment("物料编码")]
+        public string ItemNum { get; set; }
+
+        /// <summary>
+        /// 物料版本号
+        /// </summary>
+        [Comment("物料版本号")]
+        public string Version { get; set; }
+    }
+}

+ 68 - 0
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/crm_planorder.cs

@@ -0,0 +1,68 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Domain
+{
+    /// <summary>
+    /// 计划订单表
+    /// </summary>
+    [Comment("计划订单表")]
+    [Index(nameof(PlanMonth),nameof(Model),nameof(ItemNum),nameof(Type), nameof(tenant_id),nameof(company_id), nameof(factory_id), IsUnique = true)]
+    public class crm_planorder : BaseEntity
+    {
+        /// <summary>
+        /// 计划补货月份
+        /// </summary>
+        [Comment("计划补货月份")]
+        public string PlanMonth { get; set; }
+
+        /// <summary>
+        /// 规格型号
+        /// </summary>
+        [Comment("规格型号")]
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        [Comment("物料编码")]
+        public string ItemNum { get; set; }
+
+        /// <summary>
+        /// 产品线
+        /// </summary>
+        [Comment("产品线")]
+        public string ProdLine { get; set; }
+
+        /// <summary>
+        /// 产品类型
+        /// </summary>
+        [Comment("产品类型")]
+        public string ProdType { get; set; }
+
+        /// <summary>
+        /// 需补货数量
+        /// </summary>
+        [Comment("需补货数量")]
+        public decimal Qty { get; set; }
+
+        /// <summary>
+        /// 计划订单类型
+        /// </summary>
+        [Comment("计划订单类型")]
+        public string Type { get; set; }
+
+        /// <summary>
+        /// 产生方式
+        /// </summary>
+        [Comment("产生方式")]
+        public string Source { get; set; }
+    }
+}

+ 1 - 1
MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/BusinessDbContextModelCreatingExtensions.cs

@@ -48,7 +48,7 @@ namespace Business.EntityFrameworkCore
             builder.Entity<ic_item_stockoccupy>(b =>
             {
                 b.ToTable("ic_item_stockoccupy");
-                b.HasIndex(b => new { b.icitem_id, b.tenant_id, b.company_id, b.factory_id });
+                b.HasIndex(b => new { b.orderentry_id,b.icitem_number,b.fversion, b.tenant_id, b.company_id, b.factory_id });
                 //²»Ó³Éäµ½Êý¾Ý¿âÖÐ
                 b.Ignore(x => x.bang_id);
                 b.ConfigureByConvention();

+ 15 - 0
MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs

@@ -148,6 +148,11 @@ namespace Business.EntityFrameworkCore
         /// </summary>
         public DbSet<MonthlyProdCapacity> MonthlyProdCapacity { get; set; }
 
+        /// <summary>
+        /// 月度共识产能明细表
+        /// </summary>
+        public DbSet<MonthlyProdCapacityDtl> MonthlyProdCapacityDtl { get; set; }
+
         /// <summary>
         /// 标准物料规格型号设置表
         /// </summary>
@@ -188,6 +193,16 @@ namespace Business.EntityFrameworkCore
         /// </summary>
         public DbSet<PlatStockMonitorSetting> PlatStockMonitorSetting { get; set; }
 
+        /// <summary>
+        /// SKU版本号维护表
+        /// </summary>
+        public DbSet<SkuVersionSet> SkuVersionSet { get; set; }
+
+        /// <summary>
+        /// 计划订单表
+        /// </summary>
+        public DbSet<crm_planorder> crm_planorder { get; set; }
+
         /// <summary>
         /// 系统配置表
         /// </summary>

+ 11 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Attributes/NoLoginAttribute.cs

@@ -0,0 +1,11 @@
+using System;
+
+namespace Host.Attributes
+{
+    /// <summary>
+    /// 标记了此特性的方法,不需要进行登录和授权认证
+    /// </summary>
+    public class NoLoginAttribute : Attribute
+    {
+    }
+}

+ 10 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/AppConfig.cs

@@ -0,0 +1,10 @@
+using Talk.Extensions;
+
+namespace Host.Common
+{
+    public static class AppConfig
+    {
+        public static string DbProviderName => ConfigurationManager.GetTryConfig("Quartz:dbProviderName");
+        public static string ConnectionString => ConfigurationManager.GetTryConfig("Quartz:connectionString");
+    }
+}

+ 16 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/AppSetting.cs

@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Host.Common
+{
+    public class AppSetting
+    {
+        /// <summary>
+        /// 小驼峰命名
+        /// </summary>
+        public static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
+        {
+            ContractResolver = new CamelCasePropertyNamesContractResolver()
+        };
+    }
+}

+ 13 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/BaseResult.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host
+{
+    public class BaseResult
+    {
+        public int Code { get; set; } = 200;
+        public string Msg { get; set; }
+    }
+}

+ 63 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Constant.cs

@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Common
+{
+    public class Constant
+    {
+        /// <summary>
+        /// 请求url RequestUrl
+        /// </summary>
+        public const string REQUESTURL = "RequestUrl";
+        /// <summary>
+        /// 请求参数 RequestParameters
+        /// </summary>
+        public const string REQUESTPARAMETERS = "RequestParameters";
+        /// <summary>
+        /// Headers(可以包含:Authorization授权认证)
+        /// </summary>
+        public const string HEADERS = "Headers";
+        /// <summary>
+        /// 是否发送邮件
+        /// </summary>
+        public const string MAILMESSAGE = "MailMessage";
+        /// <summary>
+        /// 请求类型 RequestType
+        /// </summary>
+        public const string REQUESTTYPE = "RequestType";
+        /// <summary>
+        /// 日志 LogList
+        /// </summary>
+        public const string LOGLIST = "LogList";
+        /// <summary>
+        /// 异常 Exception
+        /// </summary>
+        public const string EXCEPTION = "Exception";
+        /// <summary>
+        /// 执行次数
+        /// </summary>
+        public const string RUNNUMBER = "RunNumber";
+
+        public const string MailTitle = "MailTitle";
+        public const string MailContent = "MailContent";
+        public const string MailTo = "MailTo";
+
+        public const string JobTypeEnum = "JobTypeEnum";
+
+        public const string EndAt = "EndAt";
+
+        public const string ClientID = "ClientID";
+        public const string Host = "Host";
+        public const string Password = "Password";
+        public const string Port = "Port";
+        public const string UserName = "UserName";
+
+        public static string Topic = "Topic";
+        public static string Payload = "Payload";
+
+        public static string RabbitQueue = "RabbitQueue";
+        public static string RabbitBody = "RabbitBody";
+    }
+}

+ 57 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/EncryptDecryptExtension.cs

@@ -0,0 +1,57 @@
+using System;
+using System.Security.Cryptography;
+using System.Text;
+using Talk.Extensions;
+
+namespace Host.Common
+{
+    public static class EncryptDecryptExtension
+    {
+
+        //可在配置文件配置自己的DES3Key - 必须16位
+        private static readonly string des3key = ConfigurationManager.GetTryConfig("DES3Key", "73495773n~@^v&B6");
+
+        /// <summary>
+        /// 加密
+        /// </summary>
+        /// <param name="data"></param>        
+        /// <returns></returns>
+        public static string DES3Encrypt(this string data)
+        {
+            byte[] inputArray = Encoding.UTF8.GetBytes(data);
+            var tripleDES = TripleDES.Create();
+            var byteKey = Encoding.UTF8.GetBytes(des3key);
+            byte[] allKey = new byte[24];
+            Buffer.BlockCopy(byteKey, 0, allKey, 0, 16);
+            Buffer.BlockCopy(byteKey, 0, allKey, 16, 8);
+            tripleDES.Key = allKey;
+            tripleDES.Mode = CipherMode.ECB;
+            tripleDES.Padding = PaddingMode.PKCS7;
+            ICryptoTransform cTransform = tripleDES.CreateEncryptor();
+            byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
+            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
+        }
+
+        /// <summary>
+        /// 解密
+        /// </summary>
+        /// <param name="data"></param>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public static string DES3Decrypt(this string data)
+        {
+            byte[] inputArray = Convert.FromBase64String(data);
+            var tripleDES = TripleDES.Create();
+            var byteKey = Encoding.UTF8.GetBytes(des3key);
+            byte[] allKey = new byte[24];
+            Buffer.BlockCopy(byteKey, 0, allKey, 0, 16);
+            Buffer.BlockCopy(byteKey, 0, allKey, 16, 8);
+            tripleDES.Key = allKey;
+            tripleDES.Mode = CipherMode.ECB;
+            tripleDES.Padding = PaddingMode.PKCS7;
+            ICryptoTransform cTransform = tripleDES.CreateDecryptor();
+            byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
+            return Encoding.UTF8.GetString(resultArray);
+        }
+    }
+}

+ 11 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/ConnectionMethod.cs

@@ -0,0 +1,11 @@
+namespace Host.Common.Enums
+{
+    public enum ConnectionMethod
+    {
+        None = 0,
+        TCP = 1,
+        TCP_SSL = 2,
+        WS = 3,
+        WSS = 4,
+    }
+}

+ 12 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/JobTypeEnum.cs

@@ -0,0 +1,12 @@
+namespace Host.Common.Enums
+{
+    public enum JobTypeEnum
+    {
+        None = 0,
+        Url = 1,
+        Emial = 2,
+        Mqtt = 3,
+        RabbitMQ = 4,
+        Hotreload = 5,
+    }
+}

+ 9 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/MailMessageEnum.cs

@@ -0,0 +1,9 @@
+namespace Host.Common
+{
+    public enum MailMessageEnum
+    {
+        None = 0,
+        Err = 1,
+        All = 2
+    }
+}

+ 16 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/RequestTypeEnum.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host
+{
+    public enum RequestTypeEnum
+    {     
+        None = 0,
+        Get = 1,
+        Post = 2,
+        Put = 4,
+        Delete = 8
+    }
+}

+ 14 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/Enums/TriggerTypeEnum.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Common
+{
+    public enum TriggerTypeEnum
+    {
+        None = 0,
+        Cron = 1,
+        Simple = 2,
+    }
+}

+ 80 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/FileConfig.cs

@@ -0,0 +1,80 @@
+using Host.Entity;
+using Newtonsoft.Json;
+using System.Threading.Tasks;
+
+namespace Host.Common
+{
+    public static class FileConfig
+    {
+        private static string filePath = "File/Mail.txt";
+
+        private static string mqttFilePath = "File/mqtt.json";
+        private static string rabbitFilePath = "File/rabbitmq.json";
+
+        private static MailEntity mailData = null;
+        public static async Task<MailEntity> GetMailInfoAsync()
+        {
+            if (mailData == null)
+            {
+                if (!System.IO.File.Exists(filePath)) return new MailEntity();
+                var mail = await System.IO.File.ReadAllTextAsync(filePath);
+                mailData = JsonConvert.DeserializeObject<MailEntity>(mail);
+            }
+            //深度复制,调用方修改。
+            return JsonConvert.DeserializeObject<MailEntity>(JsonConvert.SerializeObject(mailData));
+        }
+
+        public static async Task<bool> SaveMailInfoAsync(MailEntity mailEntity)
+        {
+            mailData = mailEntity;
+            await System.IO.File.WriteAllTextAsync(filePath, JsonConvert.SerializeObject(mailEntity));
+            return true;
+        }
+
+        /// <summary>
+        /// 保存Mqtt 配置
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static async Task<bool> SaveMqttSetAsync(MqttOptionsEntity input)
+        {
+            await System.IO.File.WriteAllTextAsync(mqttFilePath, JsonConvert.SerializeObject(input));
+            return true;
+        }
+
+        /// <summary>
+        /// 获取Mqtt 配置
+        /// </summary>
+        /// <returns></returns>
+        public static async Task<MqttOptionsEntity> GetMqttSetAsync()
+        {
+            if (!System.IO.File.Exists(mqttFilePath)) return new MqttOptionsEntity();
+
+            var entity = await System.IO.File.ReadAllTextAsync(mqttFilePath);
+            return JsonConvert.DeserializeObject<MqttOptionsEntity>(entity);
+        }
+
+        /// <summary>
+        /// 保存Rabbit 配置
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static async Task<bool> SaveRabbitSetAsync(RabbitOptionsEntity input)
+        {
+            await System.IO.File.WriteAllTextAsync(rabbitFilePath, JsonConvert.SerializeObject(input));
+            return true;
+        }
+
+        /// <summary>
+        /// 获取Rabbit 配置
+        /// </summary>
+        /// <returns></returns>
+        public static async Task<RabbitOptionsEntity> GetRabbitSetAsync()
+        {
+            if (!System.IO.File.Exists(rabbitFilePath)) return new RabbitOptionsEntity();
+
+            var entity = await System.IO.File.ReadAllTextAsync(rabbitFilePath);
+            return JsonConvert.DeserializeObject<RabbitOptionsEntity>(entity) ?? new RabbitOptionsEntity();
+        }
+    }
+}

+ 182 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/HttpHelper.cs

@@ -0,0 +1,182 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+
+
+namespace Host
+{
+    /// <summary>
+    /// 请求帮助类
+    /// </summary>
+    public class HttpHelper
+    {
+        public static readonly HttpHelper Instance;
+        static HttpHelper()
+        {
+            Instance = new HttpHelper();
+        }
+        /// <summary>
+        /// 不同url分配不同HttpClient
+        /// </summary>
+        public static ConcurrentDictionary<string, HttpClient> dictionary = new ConcurrentDictionary<string, HttpClient>();
+
+        private HttpClient GetHttpClient(string url)
+        {
+            var uri = new Uri(url);
+            var key = uri.Scheme + uri.Host;
+            //if (!dictionary.Keys.Contains(key))
+            return dictionary.GetOrAdd(key, new HttpClient());
+            //return dictionary[key];
+        }
+
+        /// <summary>
+        /// Post请求
+        /// </summary>
+        /// <param name="url">url地址</param>
+        /// <param name="jsonString">请求参数(Json字符串)</param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> PostAsync(string url, string jsonString, Dictionary<string, string> headers = null)
+        {
+            if (string.IsNullOrWhiteSpace(jsonString))
+                jsonString = "{}";
+            StringContent content = new StringContent(jsonString);
+            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+
+            if (headers != null && headers.Any())
+            {
+                //如果有headers认证等信息,则每个请求实例一个HttpClient
+                using (HttpClient http = new HttpClient())
+                {
+                    foreach (var item in headers)
+                    {
+                        http.DefaultRequestHeaders.Remove(item.Key);
+                        http.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
+                    }
+                    return await http.PostAsync(new Uri(url), content);
+                }
+            }
+            else
+            {
+                return await GetHttpClient(url).PostAsync(new Uri(url), content);
+            }
+        }
+
+        /// <summary>
+        /// Post请求
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="url">url地址</param>
+        /// <param name="content">请求参数</param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> PostAsync<T>(string url, T content, Dictionary<string, string> headers = null) where T : class
+        {
+            return await PostAsync(url, JsonConvert.SerializeObject(content), headers);
+        }
+
+        /// <summary>
+        /// Get请求
+        /// </summary>
+        /// <param name="url">url地址</param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> GetAsync(string url, Dictionary<string, string> headers = null)
+        {
+            if (headers != null && headers.Any())
+            {
+                //如果有headers认证等信息,则每个请求实例一个HttpClient
+                using (HttpClient http = new HttpClient())
+                {
+                    foreach (var item in headers)
+                    {
+                        http.DefaultRequestHeaders.Remove(item.Key);
+                        http.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
+                    }
+                    return await http.GetAsync(url);
+                }
+            }
+            else
+            {
+                return await GetHttpClient(url).GetAsync(url);
+            }
+        }
+
+        /// <summary>
+        /// Put请求
+        /// </summary>
+        /// <param name="url">url地址</param>
+        /// <param name="jsonString">请求参数(Json字符串)</param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> PutAsync(string url, string jsonString, Dictionary<string, string> headers = null)
+        {
+            if (string.IsNullOrWhiteSpace(jsonString))
+                jsonString = "{}";
+            StringContent content = new StringContent(jsonString);
+            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+            if (headers != null && headers.Any())
+            {
+                //如果有headers认证等信息,则每个请求实例一个HttpClient
+                using (HttpClient http = new HttpClient())
+                {
+                    foreach (var item in headers)
+                    {
+                        http.DefaultRequestHeaders.Remove(item.Key);
+                        http.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
+                    }
+                    return await http.PutAsync(url, content);
+                }
+            }
+            else
+            {
+                return await GetHttpClient(url).PutAsync(url, content);
+            }
+        }
+
+        /// <summary>
+        /// Put请求
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="url">url地址</param>
+        /// <param name="content">请求参数</param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> PutAsync<T>(string url, T content, Dictionary<string, string> headers = null)
+        {
+            return await PutAsync(url, JsonConvert.SerializeObject(content), headers);
+        }
+
+        /// <summary>
+        /// Delete请求
+        /// </summary>
+        /// <param name="url"></param>
+        /// <param name="headers">webapi做用户认证</param>
+        /// <returns></returns>
+        public async Task<HttpResponseMessage> DeleteAsync(string url, Dictionary<string, string> headers = null)
+        {
+            if (headers != null && headers.Any())
+            {
+                //如果有headers认证等信息,则每个请求实例一个HttpClient
+                using (HttpClient http = new HttpClient())
+                {
+                    foreach (var item in headers)
+                    {
+                        http.DefaultRequestHeaders.Remove(item.Key);
+                        http.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
+                    }
+                    return await http.DeleteAsync(url);
+                }
+            }
+            else
+            {
+                return await GetHttpClient(url).DeleteAsync(url);
+            }
+        }
+    }
+}

+ 61 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/MailHelper.cs

@@ -0,0 +1,61 @@
+using Host.Entity;
+using MimeKit;
+using System;
+using System.Security.Authentication;
+using System.Threading.Tasks;
+using Talk.Extensions;
+
+namespace Host.Common
+{
+    public static class MailHelper
+    {
+        public static async Task<bool> SendMail(string title, string content, MailEntity mailInfo = null)
+        {
+            if (mailInfo == null)
+            {
+                mailInfo = await FileConfig.GetMailInfoAsync();
+                if (mailInfo.MailPwd.IsNullOrWhiteSpace() ||
+                    mailInfo.MailFrom.IsNullOrWhiteSpace() ||
+                    mailInfo.MailHost.IsNullOrWhiteSpace())
+                {
+                    throw new Exception("请先在 [/seting] 页面配置邮箱设置。");
+                }
+            }
+            else
+            {
+                mailInfo.MailFrom = mailInfo.MailFrom.Trim();
+                mailInfo.MailHost = mailInfo.MailHost.Trim();
+                mailInfo.MailTo = mailInfo.MailTo.Trim();
+            }
+
+            var message = new MimeMessage();
+            message.From.Add(new MailboxAddress(mailInfo.MailFrom, mailInfo.MailFrom));
+            foreach (var mailTo in mailInfo.MailTo.Replace(";", ";").Replace(",", ";").Replace(",", ";").Split(';'))
+            {
+                message.To.Add(new MailboxAddress(mailTo, mailTo));
+            }
+            message.Subject = string.Format(title);
+            message.Body = new TextPart("html")
+            {
+                Text = content
+            };
+            using (var client = new MailKit.Net.Smtp.SmtpClient())
+            {
+                await client.ConnectAsync(mailInfo.MailHost, 465, true);
+                await client.AuthenticateAsync(mailInfo.MailFrom, mailInfo.MailPwd);
+                await client.SendAsync(message);
+                await client.DisconnectAsync(true);
+            }
+            return true;
+        }
+
+        public static async Task<bool> SendMail(string title, string content, string mailTo)
+        {
+            var info = await FileConfig.GetMailInfoAsync();
+            if (info.MailPwd.IsNullOrWhiteSpace() || info.MailFrom.IsNullOrWhiteSpace() || info.MailHost.IsNullOrWhiteSpace())
+                throw new Exception("请先在 [/seting] 页面配置邮箱设置。");
+            info.MailTo = mailTo;
+            return await SendMail(title, content, info);
+        }
+    }
+}

+ 16 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Common/StringExtension.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Common
+{
+    public static class StringExtension
+    {
+        public static string ToBase64(this string str)
+        {
+            byte[] base64 = System.Text.Encoding.Default.GetBytes(str);
+            return Convert.ToBase64String(base64);
+        }
+    }
+}

+ 219 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Controllers/JobController.cs

@@ -0,0 +1,219 @@
+using Host.Common;
+using Host.Entity;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.Mvc;
+using Quartz;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Talk.Extensions;
+
+namespace Host.Controllers
+{
+    /// <summary>
+    /// 任务调度
+    /// </summary>
+    [Route("api/[controller]/[Action]")]
+    [EnableCors("AllowSameDomain")] //允许跨域 
+    public class JobController : Controller
+    {
+        private SchedulerCenter scheduler;
+
+        /// <summary>
+        /// 任务调度对象
+        /// </summary>
+        /// <param name="schedulerCenter"></param>
+        public JobController(SchedulerCenter schedulerCenter)
+        {
+            scheduler = schedulerCenter;
+        }
+
+        /// <summary>
+        /// 添加任务
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<BaseResult> AddJob([FromBody] ScheduleEntity entity)
+        {
+            if (ConfigurationManager.GetTryConfig("EnvironmentalRestrictions", "false") == "true")
+            {
+                if (entity.TriggerType == TriggerTypeEnum.Simple &&
+                    entity.IntervalSecond.HasValue &&
+                    entity.IntervalSecond <= 10)
+                {
+                    return new BaseResult()
+                    {
+                        Code = 403,
+                        Msg = "当前环境不允许低于10秒内循环执行任务!"
+                    };
+                }
+                else if (entity.TriggerType == TriggerTypeEnum.Cron &&
+                         entity.Cron == "* * * * * ?")
+                {
+                    return new BaseResult()
+                    {
+                        Code = 403,
+                        Msg = "当前环境不允许过频繁执行任务!"
+                    };
+                }
+
+            }
+            return await scheduler.AddScheduleJobAsync(entity);
+        }
+
+        /// <summary>
+        /// 暂停任务
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<BaseResult> StopJob([FromBody] JobKey job)
+        {
+            return await scheduler.StopOrDelScheduleJobAsync(job.Group, job.Name);
+        }
+
+        /// <summary>
+        /// 删除任务
+        /// </summary> 
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<BaseResult> RemoveJob([FromBody] JobKey job)
+        {
+            return await scheduler.StopOrDelScheduleJobAsync(job.Group, job.Name, true);
+        }
+
+        /// <summary>
+        /// 恢复运行暂停的任务
+        /// </summary> 
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<BaseResult> ResumeJob([FromBody] JobKey job)
+        {
+            return await scheduler.ResumeJobAsync(job.Group, job.Name);
+        }
+
+        /// <summary>
+        /// 查询任务
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<ScheduleEntity> QueryJob([FromBody] JobKey job)
+        {
+            return await scheduler.QueryJobAsync(job.Group, job.Name);
+        }
+
+        /// <summary>
+        /// 修改
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<BaseResult> ModifyJob([FromBody] ModifyJobInput entity)
+        {
+            if (ConfigurationManager.GetTryConfig("EnvironmentalRestrictions", "false") == "true")
+            {
+
+                if (entity.NewScheduleEntity.TriggerType == TriggerTypeEnum.Simple &&
+                    entity.NewScheduleEntity.IntervalSecond.HasValue &&
+                    entity.NewScheduleEntity.IntervalSecond <= 10)
+                {
+                    return new BaseResult()
+                    {
+                        Code = 403,
+                        Msg = "当前环境不允许低于10秒内循环执行任务!"
+                    };
+                }
+                else if (entity.NewScheduleEntity.TriggerType == TriggerTypeEnum.Cron &&
+                    entity.NewScheduleEntity.Cron == "* * * * * ?")
+                {
+                    return new BaseResult()
+                    {
+                        Code = 403,
+                        Msg = "当前环境不允许过频繁执行任务!"
+                    };
+                }
+            }
+
+            var jobKey = new JobKey(entity.OldScheduleEntity.JobName, entity.OldScheduleEntity.JobGroup);
+            var runNumber = await scheduler.GetRunNumberAsync(jobKey);
+            await scheduler.StopOrDelScheduleJobAsync(entity.OldScheduleEntity.JobGroup, entity.OldScheduleEntity.JobName, true);
+            await scheduler.AddScheduleJobAsync(entity.NewScheduleEntity, runNumber);
+            return new BaseResult() { Msg = "修改计划任务成功!" };
+        }
+
+        /// <summary>
+        /// 立即执行
+        /// </summary>
+        /// <param name="job"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> TriggerJob([FromBody] JobKey job)
+        {
+            await scheduler.TriggerJobAsync(job);
+            return true;
+        }
+
+        /// <summary>
+        /// 获取job日志
+        /// </summary>
+        /// <param name="jobKey"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<List<string>> GetJobLogs([FromBody] JobKey jobKey)
+        {
+            var logs = await scheduler.GetJobLogsAsync(jobKey);
+            logs?.Reverse();
+            return logs;
+        }
+
+        /// <summary>
+        /// 启动调度
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public async Task<bool> StartSchedule()
+        {
+            return await scheduler.StartScheduleAsync();
+        }
+
+        /// <summary>
+        /// 停止调度
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public async Task<bool> StopSchedule()
+        {
+            return await scheduler.StopScheduleAsync();
+        }
+
+        /// <summary>
+        /// 获取所有任务
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public async Task<List<JobInfoEntity>> GetAllJob()
+        {
+            return await scheduler.GetAllJobAsync();
+        }
+
+        /// <summary>
+        /// 获取所有Job信息(简要信息 - 刷新数据的时候使用)
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public async Task<List<JobBriefInfoEntity>> GetAllJobBriefInfo()
+        {
+            return await scheduler.GetAllJobBriefInfoAsync();
+        }
+
+        /// <summary>
+        /// 移除异常信息
+        /// </summary>
+        /// <param name="jobKey"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> RemoveErrLog([FromBody] JobKey jobKey)
+        {
+            return await scheduler.RemoveErrLog(jobKey.Group, jobKey.Name);
+        }
+    }
+}

+ 208 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Controllers/SetingController.cs

@@ -0,0 +1,208 @@
+using Host.Attributes;
+using Host.Common;
+using Host.Entity;
+using Host.Managers;
+using Host.Model;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.Mvc;
+using MimeKit;
+using Newtonsoft.Json;
+using System;
+using System.Threading.Tasks;
+using Talk.Extensions;
+
+namespace Host.Controllers
+{
+    /// <summary>
+    /// 设置
+    /// </summary>
+    [Route("api/[controller]/[Action]")]
+    [EnableCors("AllowSameDomain")] //允许跨域 
+    public class SetingController : Controller
+    {
+        private static string refreshIntervalPath = "File/RefreshInterval.json";
+        private static string loginPasswordPath = "File/LoginPassword.json";
+
+        private static UpdateLoginInfoEntity LoginInfo = null;
+        /// <summary>
+        /// 保存Mail信息
+        /// </summary>
+        /// <param name="mailEntity"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> SaveMailInfo([FromBody] MailEntity mailEntity)
+        {
+            return await FileConfig.SaveMailInfoAsync(mailEntity);
+        }
+
+        /// <summary>
+        /// 保存Mqtt的配置
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> SaveMqttSet([FromBody] MqttOptionsEntity input)
+        {
+            await FileConfig.SaveMqttSetAsync(input);
+            await MqttManager.Instance.RestartAsync();
+            return true;
+        }
+
+        /// <summary>
+        /// 获取Mqtt的配置
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<MqttOptionsEntity> GetMqttSet()
+        {
+            return await FileConfig.GetMqttSetAsync();
+        }
+
+        /// <summary>
+        /// 保存Rabbit 配置
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> SaveRabbitSet([FromBody] RabbitOptionsEntity input)
+        {
+            await FileConfig.SaveRabbitSetAsync(input);
+            return true;
+        }
+
+        /// <summary>
+        /// 重启Rabbit
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> RestartRabbit()
+        {
+            return await RabbitMQManager.Instance.RestartAsync();
+        }
+
+        /// <summary>
+        /// 获取Rabbit的配置
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<RabbitOptionsEntity> GetRabbitSet()
+        {
+            return await FileConfig.GetRabbitSetAsync();
+        }
+
+        /// <summary>
+        /// 保存刷新间隔
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> SaveRefreshInterval([FromBody] RefreshIntervalEntity entity)
+        {
+            await System.IO.File.WriteAllTextAsync(refreshIntervalPath, JsonConvert.SerializeObject(entity));
+            return true;
+        }
+
+        /// <summary>
+        /// 保存登录密码
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<bool> SaveLoginInfo([FromBody] UpdateLoginInfoEntity entity)
+        {
+            LoginInfo = await GetLoginAsync();
+            if (LoginInfo.NewPassword == entity.OldPassword)
+            {
+                await System.IO.File.WriteAllTextAsync(loginPasswordPath, JsonConvert.SerializeObject(entity));
+                LoginInfo = entity;
+                return true;
+            }
+            return false;
+        }
+
+        private static DateTime ErrLoginTime = DateTime.MinValue;
+        private static int LoginNumber = 0;
+        /// <summary>
+        /// 登录
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [NoLogin]
+        public async Task<LoginInfoOutput> VerifyLoginInfo([FromBody] LoginInfoEntity input)
+        {
+            var output = new LoginInfoOutput();
+
+            //防止暴力破解,2分钟内只允许错误20次。
+            if (LoginNumber++ >= 20 || ErrLoginTime.AddMinutes(2) >= DateTime.Now)
+            {
+                ErrLoginTime = DateTime.Now;
+                LoginNumber = 0;
+                return output;
+            }
+
+            LoginInfo = await GetLoginAsync();
+            if (input.Password == LoginInfo.NewPassword.ToBase64())
+            {
+                output.Token = $"{DateTime.Now}".DES3Encrypt();
+                LoginNumber = 0;
+            }
+            else
+            {
+                var defaultPassword = ConfigurationManager.GetTryConfig("DefaultPassword");
+                if (!string.IsNullOrWhiteSpace(defaultPassword) && input.Password == defaultPassword.ToBase64())
+                {
+                    output.Token = $"{DateTime.Now}".DES3Encrypt();
+                    LoginNumber = 0;
+                }
+            }
+            return output;
+        }
+
+        /// <summary>
+        /// 获取登录信息
+        /// </summary>
+        /// <returns></returns>
+        private async Task<UpdateLoginInfoEntity> GetLoginAsync()
+        {
+            if (LoginInfo == null)
+            {
+                if (!System.IO.File.Exists(loginPasswordPath))
+                    await System.IO.File.WriteAllTextAsync(loginPasswordPath, JsonConvert.SerializeObject(new UpdateLoginInfoEntity()));
+                LoginInfo = JsonConvert.DeserializeObject<UpdateLoginInfoEntity>(await System.IO.File.ReadAllTextAsync(loginPasswordPath)) ?? new UpdateLoginInfoEntity();
+            }
+            return LoginInfo;
+        }
+
+        /// <summary>
+        /// 获取
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<RefreshIntervalEntity> GetRefreshInterval()
+        {
+            return JsonConvert.DeserializeObject<RefreshIntervalEntity>(await System.IO.File.ReadAllTextAsync(refreshIntervalPath)) ?? new RefreshIntervalEntity();
+        }
+
+        /// <summary>
+        /// 获取eMail信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task<MailEntity> GetMailInfo()
+        {
+            return await FileConfig.GetMailInfoAsync();
+        }
+
+        /// <summary>
+        /// 发送邮件
+        /// </summary>
+        /// <param name="model"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [NoLogin]
+        public async Task<bool> SendMail([FromBody] SendMailModel model)
+        {
+            return await MailHelper.SendMail(model.Title, model.Content, model.MailInfo);
+        }
+    }
+}

+ 23 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Dockerfile

@@ -0,0 +1,23 @@
+
+#基础镜像(用来构建镜像)
+FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
+WORKDIR /app
+EXPOSE 80
+RUN apk add -U tzdata
+RUN apk add icu-libs
+ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
+RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+RUN cp /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Beijing
+
+#编译(临时镜像,主要用来编译发布项目)
+FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS publish
+WORKDIR /src
+COPY . .
+WORKDIR /src/Host
+RUN dotnet publish -c Release -o /app
+
+#构建镜像
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app .
+CMD ["dotnet", "Host.dll"]

+ 21 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Dockerfile[树莓派]

@@ -0,0 +1,21 @@
+#基础镜像(用来构建镜像)
+FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim-arm32v7 AS base
+WORKDIR /app
+EXPOSE 80
+ENV TZ=Asia/Shanghai
+CMD cp /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Beijing
+CMD ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+#编译(临时镜像,主要用来编译发布项目)
+FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS publish
+WORKDIR /src
+COPY . .
+WORKDIR /src/Host
+#RUN dotnet publish -c Release -o /app
+RUN dotnet publish -r debian-arm -c Release -o /app
+
+#构建镜像
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app .
+CMD ["dotnet", "Host.dll"]

+ 90 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/JobBriefInfoEntity.cs

@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Quartz;
+
+namespace Host.Entity
+{
+    public class JobBriefInfoEntity
+    {
+        /// <summary>
+        /// 任务组名
+        /// </summary>
+        public string GroupName { get; set; }
+
+        /// <summary>
+        /// 任务信息
+        /// </summary>
+        public List<JobBriefInfo> JobInfoList { get; set; } = new List<JobBriefInfo>();
+    }
+
+    public class JobBriefInfo
+    {
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 下次执行时间
+        /// </summary>
+        public DateTime? NextFireTime { get; set; }
+
+        /// <summary>
+        /// 上次执行时间
+        /// </summary>
+        public DateTime? PreviousFireTime { get; set; }
+
+        /// <summary>
+        /// 上次执行的异常信息
+        /// </summary>
+        public string LastErrMsg { get; set; }
+
+        /// <summary>
+        /// 任务状态
+        /// </summary>
+        public TriggerState TriggerState { get; set; }
+
+        /// <summary>
+        /// 显示状态
+        /// </summary>
+        public string DisplayState
+        {
+            get
+            {
+                var state = string.Empty;
+                switch (TriggerState)
+                {
+                    case TriggerState.Normal:
+                        state = "正常";
+                        break;
+                    case TriggerState.Paused:
+                        state = "暂停";
+                        break;
+                    case TriggerState.Complete:
+                        state = "完成";
+                        break;
+                    case TriggerState.Error:
+                        state = "异常";
+                        break;
+                    case TriggerState.Blocked:
+                        state = "阻塞";
+                        break;
+                    case TriggerState.None:
+                        state = "不存在";
+                        break;
+                    default:
+                        state = "未知";
+                        break;
+                }
+                return state;
+            }
+        }
+
+        /// <summary>
+        /// 已经执行次数
+        /// </summary>
+        public long RunNumber { get; set; }
+    }
+}

+ 116 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/JobInfoEntity.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Quartz;
+
+namespace Host.Entity
+{
+    public class JobInfoEntity
+    {
+        /// <summary>
+        /// 任务组名
+        /// </summary>
+        public string GroupName { get; set; }
+
+        /// <summary>
+        /// 任务信息
+        /// </summary>
+        public List<JobInfo> JobInfoList { get; set; } = new List<JobInfo>();
+    }
+
+    public class JobInfo
+    {
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 下次执行时间
+        /// </summary>
+        public DateTime? NextFireTime { get; set; }
+
+        /// <summary>
+        /// 上次执行时间
+        /// </summary>
+        public DateTime? PreviousFireTime { get; set; }
+
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public DateTime BeginTime { get; set; }
+
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public DateTime? EndTime { get; set; }
+
+        /// <summary>
+        /// 上次执行的异常信息
+        /// </summary>
+        public string LastErrMsg { get; set; }
+
+        /// <summary>
+        /// 任务状态
+        /// </summary>
+        public TriggerState TriggerState { get; set; }
+
+        /// <summary>
+        /// 描述
+        /// </summary>
+        public string Description { get; set; }
+
+        /// <summary>
+        /// 显示状态
+        /// </summary>
+        public string DisplayState
+        {
+            get
+            {
+                var state = string.Empty;
+                switch (TriggerState)
+                {
+                    case TriggerState.Normal:
+                        state = "正常";
+                        break;
+                    case TriggerState.Paused:
+                        state = "暂停";
+                        break;
+                    case TriggerState.Complete:
+                        state = "完成";
+                        break;
+                    case TriggerState.Error:
+                        state = "异常";
+                        break;
+                    case TriggerState.Blocked:
+                        state = "阻塞";
+                        break;
+                    case TriggerState.None:
+                        state = "不存在";
+                        break;
+                    default:
+                        state = "未知";
+                        break;
+                }
+                return state;
+            }
+        }
+
+        /// <summary>
+        /// 时间间隔
+        /// </summary>
+        public string Interval { get; set; }
+
+        /// <summary>
+        /// 触发地址
+        /// </summary>
+        public string TriggerAddress { get; set; }
+        public string RequestType { get; set; }
+        /// <summary>
+        /// 已经执行的次数
+        /// </summary>
+        public long RunNumber { get; set; }
+        public long JobType { get; set; }
+    }
+}

+ 12 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/LoginInfoEntity.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class LoginInfoEntity
+    {
+        public string Password { get; set; }
+    }
+}

+ 12 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/LoginInfoOutput.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class LoginInfoOutput
+    {
+        public string Token { get; set; }
+    }
+}

+ 27 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/MailEntity.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class MailEntity
+    {
+        /// <summary>
+        /// 发件邮箱
+        /// </summary>
+        public string MailFrom { get; set; }
+        /// <summary>
+        /// 邮箱密码
+        /// </summary>
+        public string MailPwd { get; set; }
+        /// <summary>
+        /// 发件服务器
+        /// </summary>
+        public string MailHost { get; set; }
+        /// <summary>
+        /// 收件邮箱
+        /// </summary>
+        public string MailTo { get; set; }
+    }
+}

+ 13 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/ModifyJobInput.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class ModifyJobInput
+    {
+        public ScheduleEntity NewScheduleEntity { get; set; }
+        public ScheduleEntity OldScheduleEntity { get; set; }
+    }
+}

+ 15 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/MqttOptionsEntity.cs

@@ -0,0 +1,15 @@
+using Host.Common.Enums;
+
+namespace Host.Entity
+{
+    public class MqttOptionsEntity
+    {
+        public string ClientId { get; set; }
+        public string Host { get; set; }
+        public string Port { get; set; }
+        public string UserName { get; set; }
+        public string Password { get; set; }
+
+        public ConnectionMethod ConnectionMethod { get; set; }
+    }
+}

+ 15 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/RabbitOptionsEntity.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class RabbitOptionsEntity
+    {
+        public string RabbitHost { get; set; }
+        public int RabbitPort { get; set; }
+        public string RabbitUserName { get; set; }
+        public string RabbitPassword { get; set; }
+    }
+}

+ 15 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/RefreshIntervalEntity.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class RefreshIntervalEntity
+    {
+        /// <summary>
+        /// 间隔时间
+        /// </summary>
+        public int IntervalTime { get; set; } = 10;
+    }
+}

+ 93 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/ScheduleEntity.cs

@@ -0,0 +1,93 @@
+using Host.Common;
+using Host.Common.Enums;
+using System;
+
+namespace Host
+{
+    public class ScheduleEntity
+    {
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string JobName { get; set; }
+        /// <summary>
+        /// 任务分组
+        /// </summary>
+        public string JobGroup { get; set; }
+        /// <summary>
+        /// 任务类型
+        /// </summary>
+        public JobTypeEnum JobType { get; set; } = JobTypeEnum.Url;
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public DateTimeOffset BeginTime { get; set; } = DateTime.Now;
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public DateTimeOffset? EndTime { get; set; }
+        /// <summary>
+        /// Cron表达式
+        /// </summary>
+        public string Cron { get; set; }
+        /// <summary>
+        /// 执行次数(默认无限循环)
+        /// </summary>
+        public int? RunTimes { get; set; }
+        /// <summary>
+        /// 执行间隔时间,单位秒(如果有Cron,则IntervalSecond失效)
+        /// </summary>
+        public int? IntervalSecond { get; set; }
+        /// <summary>
+        /// 触发器类型
+        /// </summary>
+        public TriggerTypeEnum TriggerType { get; set; }
+        /// <summary>
+        /// 描述
+        /// </summary>
+        public string Description { get; set; }
+
+        public MailMessageEnum MailMessage { get; set; }
+
+        #region Url
+        /// <summary>
+        /// 请求url
+        /// </summary>
+        public string RequestUrl { get; set; }
+        /// <summary>
+        /// 请求参数(Post,Put请求用)
+        /// </summary>
+        public string RequestParameters { get; set; }
+        /// <summary>
+        /// Headers(可以包含如:Authorization授权认证)
+        /// 格式:{"Authorization":"userpassword.."}
+        /// </summary>
+        public string Headers { get; set; }
+        /// <summary>
+        /// 请求类型
+        /// </summary>
+        public RequestTypeEnum RequestType { get; set; } = RequestTypeEnum.Post;
+        #endregion
+
+        #region Emial
+        public string MailTitle { get; set; }
+        public string MailContent { get; set; }
+        public string MailTo { get; set; }
+        #endregion
+
+        #region MQTT
+        /// Topic 主题
+        /// </summary>
+        public string Topic { get; set; }
+        /// <summary>
+        /// Payload
+        /// </summary>
+        public string Payload { get; set; }
+        #endregion
+
+        #region Rabbit
+        public string RabbitQueue { get; set; }
+        public string RabbitBody { get; set; }
+        #endregion
+    }
+}

+ 13 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Entity/UpdateLoginInfoEntity.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Entity
+{
+    public class UpdateLoginInfoEntity
+    {
+        public string OldPassword { get; set; } = string.Empty;
+        public string NewPassword { get; set; } = string.Empty;
+    }
+}

+ 1 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/File/LoginPassword.json

@@ -0,0 +1 @@
+{"OldPassword":"","NewPassword":"admin2023"}

+ 1 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/File/RefreshInterval.json

@@ -0,0 +1 @@
+{"IntervalTime":1}

+ 1 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/File/rabbitmq.json

@@ -0,0 +1 @@
+{"RabbitHost":"47.100.89.194","RabbitPort":5672,"RabbitUserName":"guest","RabbitPassword":"guest"}

+ 55 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Filters/AuthorizationFilter.cs

@@ -0,0 +1,55 @@
+using Host.Attributes;
+using Host.Common;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Talk.Extensions;
+
+namespace Host.Filters
+{
+    public class AuthorizationFilter : IAsyncAuthorizationFilter
+    {
+        public Task OnAuthorizationAsync(AuthorizationFilterContext context)
+        {
+            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
+            {
+                var noNeedLoginAttribute = controllerActionDescriptor.
+                                   ControllerTypeInfo.
+                                   GetCustomAttributes(true)
+                                   .Where(a => a.GetType().Equals(typeof(NoLoginAttribute)))
+                                   .ToList();
+                noNeedLoginAttribute.AddRange(controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
+                                 .Where(a => a.GetType().Equals(typeof(NoLoginAttribute))).ToList());
+
+                //如果标记了 NoLoginAttribute 则不验证其登录状态
+                if (noNeedLoginAttribute.Any())
+                {
+                    return Task.CompletedTask;
+                }
+            }
+
+            var token = context.HttpContext.Request.Headers["token"].ToString();
+            if (!token.IsNullOrWhiteSpace())
+            {
+                var time = token.DES3Decrypt().ToDateTime();
+                //登录信息有效期为当天
+                if (DateTime.Now.Date == time.Date)
+                {
+                    return Task.CompletedTask;
+                }
+            }
+
+            context.Result = new JsonResult(new
+            {
+                ErrorMsg = "请登录",
+                ResultUrl = "/signin",
+            });
+            context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
+            return Task.CompletedTask;
+        }
+    }
+}

+ 94 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Host.csproj

@@ -0,0 +1,94 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <DocumentationFile>bin\Debug\netcoreapp2.0\Host.xml</DocumentationFile>
+    <WarningsAsErrors>NU1605</WarningsAsErrors>
+    <NoWarn>1701;1702;CS1591;CS1572</NoWarn>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <DocumentationFile>bin\Release\netcoreapp2.0\Host.xml</DocumentationFile>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Remove="logs\**" />
+    <Content Remove="logs\**" />
+    <EmbeddedResource Remove="logs\**" />
+    <None Remove="logs\**" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Remove="Model\LogInfoModel.cs" />
+    <Compile Remove="ScheduleManage.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Remove="sqliteScheduler.db" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="wwwroot\" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Dapper" Version="2.0.78" />
+    <PackageReference Include="Dapper.Contrib" Version="2.0.78" />
+    <PackageReference Include="MailKit" Version="3.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.2" />
+    <PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.2" />    
+    <PackageReference Include="Microsoft.Data.SQLite" Version="5.0.2" />    
+    <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />    
+    <PackageReference Include="MQTTnet" Version="3.0.13" />    
+    <PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="3.0.13" />
+    <PackageReference Include="MySql.Data" Version="8.0.23" />
+    <PackageReference Include="Npgsql" Version="5.0.3" />
+    <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.19.101" />
+    <PackageReference Include="Quartz" Version="3.3.2" />
+    <PackageReference Include="Quartz.Serialization.Json" Version="3.3.2" />
+    <PackageReference Include="RabbitMQ.Client" Version="6.2.1" />
+    <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
+    <PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
+    <PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
+    <PackageReference Include="Talk.Extensions" Version="1.0.1.67" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="Dockerfile">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="Dockerfile[树莓派]">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_firebird.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_mysql_innodb.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_oracle.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_postgres.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_sqlite.sql">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_sqlServer.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Update="Tables\tables_sqlServerMOT.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+
+</Project>

+ 10 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Host.csproj.user

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ActiveDebugProfile>Host</ActiveDebugProfile>
+    <NameOfLastUsedPublishProfile>FolderProfile</NameOfLastUsedPublishProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
+  </PropertyGroup>
+</Project>

+ 83 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/HttpJob.cs

@@ -0,0 +1,83 @@
+using Host.Common;
+using Host.IJobs;
+using Host.IJobs.Model;
+using Host.Model;
+using Newtonsoft.Json;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web;
+using Talk.Extensions;
+
+namespace Host
+{
+    public class HttpJob : JobBase<LogUrlModel>, IJob
+    {
+        public HttpJob() : base(new LogUrlModel())
+        { }
+
+        public override async Task NextExecute(IJobExecutionContext context)
+        {
+            //获取相关参数
+            var requestUrl = context.JobDetail.JobDataMap.GetString(Constant.REQUESTURL)?.Trim();
+            requestUrl = requestUrl?.IndexOf("http") == 0 ? requestUrl : "http://" + requestUrl;
+            var requestParameters = context.JobDetail.JobDataMap.GetString(Constant.REQUESTPARAMETERS);
+            var headersString = context.JobDetail.JobDataMap.GetString(Constant.HEADERS);
+            var headers = headersString != null ? JsonConvert.DeserializeObject<Dictionary<string, string>>(headersString?.Trim()) : null;
+            var requestType = (RequestTypeEnum)int.Parse(context.JobDetail.JobDataMap.GetString(Constant.REQUESTTYPE));
+
+
+            LogInfo.Url = requestUrl;
+            LogInfo.RequestType = requestType.ToString();
+            LogInfo.Parameters = requestParameters;
+
+            HttpResponseMessage response = new HttpResponseMessage();
+            var http = HttpHelper.Instance;
+            switch (requestType)
+            {
+                case RequestTypeEnum.Get:
+                    response = await http.GetAsync(requestUrl, headers);
+                    break;
+                case RequestTypeEnum.Post:
+                    response = await http.PostAsync(requestUrl, requestParameters, headers);
+                    break;
+                case RequestTypeEnum.Put:
+                    response = await http.PutAsync(requestUrl, requestParameters, headers);
+                    break;
+                case RequestTypeEnum.Delete:
+                    response = await http.DeleteAsync(requestUrl, headers);
+                    break;
+            }
+            var result = HttpUtility.HtmlEncode(await response.Content.ReadAsStringAsync());
+            LogInfo.Result = $"<span class='result'>{result.MaxLeft(1000)}</span>";
+            if (!response.IsSuccessStatusCode)
+            {
+                LogInfo.ErrorMsg = $"<span class='error'>{result.MaxLeft(3000)}</span>";
+                await ErrorAsync(LogInfo.JobName, new Exception(result.MaxLeft(3000)), JsonConvert.SerializeObject(LogInfo), MailLevel);
+                context.JobDetail.JobDataMap[Constant.EXCEPTION] = $"<div class='err-time'>{LogInfo.BeginTime}</div>{JsonConvert.SerializeObject(LogInfo)}";
+            }
+            else
+            {
+                try
+                {
+                    //这里需要和请求方约定好返回结果约定为HttpResultModel模型
+                    var httpResult = JsonConvert.DeserializeObject<HttpResultModel>(HttpUtility.HtmlDecode(result));
+                    if (!httpResult.IsSuccess)
+                    {
+                        LogInfo.ErrorMsg = $"<span class='error'>{httpResult.ErrorMsg}</span>";
+                        await ErrorAsync(LogInfo.JobName, new Exception(httpResult.ErrorMsg), JsonConvert.SerializeObject(LogInfo), MailLevel);
+                        context.JobDetail.JobDataMap[Constant.EXCEPTION] = $"<div class='err-time'>{LogInfo.BeginTime}</div>{JsonConvert.SerializeObject(LogInfo)}";
+                    }
+                    else
+                        await InformationAsync(LogInfo.JobName, JsonConvert.SerializeObject(LogInfo), MailLevel);
+                }
+                catch (Exception)
+                {
+                    await InformationAsync(LogInfo.JobName, JsonConvert.SerializeObject(LogInfo), MailLevel);
+                }
+            }
+        }
+    }
+}

+ 125 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/JobBase.cs

@@ -0,0 +1,125 @@
+using Host.Common;
+using Host.Controllers;
+using Host.IJobs.Model;
+using Host.Model;
+using Newtonsoft.Json;
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+namespace Host.IJobs
+{
+    [DisallowConcurrentExecution]
+    [PersistJobDataAfterExecution]
+    public abstract class JobBase<T> where T : LogModel, new()
+    {
+        protected readonly int maxLogCount = 20;//最多保存日志数量  
+        protected readonly int warnTime = 20;//接口请求超过多少秒记录警告日志 
+        protected Stopwatch stopwatch = new Stopwatch();
+        protected T LogInfo { get; private set; }
+        protected MailMessageEnum MailLevel = MailMessageEnum.None;
+
+        public JobBase(T logInfo)
+        {
+            LogInfo = logInfo;
+        }
+
+        public async Task Execute(IJobExecutionContext context)
+        {
+            //如果结束时间超过当前时间,则暂停当前任务。
+            var endTime = context.JobDetail.JobDataMap.GetString("EndAt");
+            if (!string.IsNullOrWhiteSpace(endTime) && DateTime.Parse(endTime) <= DateTime.Now)
+            {
+                await context.Scheduler.PauseJob(new JobKey(context.JobDetail.Key.Name, context.JobDetail.Key.Group));
+                return;
+            }
+
+            MailLevel = (MailMessageEnum)int.Parse(context.JobDetail.JobDataMap.GetString(Constant.MAILMESSAGE) ?? "0");
+            //记录执行次数
+            var runNumber = context.JobDetail.JobDataMap.GetLong(Constant.RUNNUMBER);
+            context.JobDetail.JobDataMap[Constant.RUNNUMBER] = ++runNumber;
+
+            var logs = context.JobDetail.JobDataMap[Constant.LOGLIST] as List<string> ?? new List<string>();
+            if (logs.Count >= maxLogCount)
+                logs.RemoveRange(0, logs.Count - maxLogCount);
+
+            stopwatch.Restart(); //  开始监视代码运行时间
+            try
+            {
+                LogInfo.BeginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+                LogInfo.JobName = $"{context.JobDetail.Key.Group}.{context.JobDetail.Key.Name}";
+
+                await NextExecute(context);
+            }
+            catch (Exception ex)
+            {
+                LogInfo.ErrorMsg = $"<span class='error'>{ex.Message}</span>";
+                context.JobDetail.JobDataMap[Constant.EXCEPTION] = $"<div class='err-time'>{LogInfo.BeginTime}</div>{JsonConvert.SerializeObject(LogInfo)}";
+                await ErrorAsync(LogInfo.JobName, ex, JsonConvert.SerializeObject(LogInfo), MailLevel);
+            }
+            finally
+            {
+                stopwatch.Stop(); //  停止监视            
+                double seconds = stopwatch.Elapsed.TotalSeconds;  //总秒数             
+                LogInfo.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+
+                if (seconds >= 1)
+                    LogInfo.ExecuteTime = seconds + "秒";
+                else
+                    LogInfo.ExecuteTime = stopwatch.Elapsed.TotalMilliseconds + "毫秒";
+
+                var classErr = string.IsNullOrWhiteSpace(LogInfo.ErrorMsg) ? "" : "error";
+                logs.Add($"<p class='msgList {classErr}'><span class='time'>{LogInfo.BeginTime} 至 {LogInfo.EndTime}  【耗时】{LogInfo.ExecuteTime}</span>{JsonConvert.SerializeObject(LogInfo)}</p>");
+                context.JobDetail.JobDataMap[Constant.LOGLIST] = logs;
+                if (seconds >= warnTime)//如果请求超过20秒,记录警告日志    
+                {
+                    await WarningAsync(LogInfo.JobName, "耗时过长 - " + JsonConvert.SerializeObject(LogInfo), MailLevel);
+                }
+            }
+        }
+
+        public abstract Task NextExecute(IJobExecutionContext context);
+
+        public async Task WarningAsync(string title, string msg, MailMessageEnum mailMessage)
+        {
+            Log.Logger.Warning(msg);
+            if (mailMessage == MailMessageEnum.All)
+            {
+                await new SetingController().SendMail(new SendMailModel()
+                {
+                    Title = $"任务调度-{title}【警告】消息",
+                    Content = msg
+                });
+            }
+        }
+
+        public async Task InformationAsync(string title, string msg, MailMessageEnum mailMessage)
+        {
+            Log.Logger.Information(msg);
+            if (mailMessage == MailMessageEnum.All)
+            {
+                await new SetingController().SendMail(new SendMailModel()
+                {
+                    Title = $"任务调度-{title}消息",
+                    Content = msg
+                });
+            }
+        }
+
+        public async Task ErrorAsync(string title, Exception ex, string msg, MailMessageEnum mailMessage)
+        {
+            Log.Logger.Error(ex, msg);
+            if (mailMessage == MailMessageEnum.Err || mailMessage == MailMessageEnum.All)
+            {
+                await new SetingController().SendMail(new SendMailModel()
+                {
+                    Title = $"任务调度-{title}【异常】消息",
+                    Content = msg
+                });
+            }
+        }
+    }
+}

+ 28 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/MailJob.cs

@@ -0,0 +1,28 @@
+using Host.Common;
+using Host.IJobs.Model;
+using Quartz;
+using System.Threading.Tasks;
+
+namespace Host.IJobs
+{
+    public class MailJob : JobBase<LogMailModel>, IJob
+    {
+        public MailJob() : base(new LogMailModel())
+        { }
+
+        public override async Task NextExecute(IJobExecutionContext context)
+        {
+            var title = context.JobDetail.JobDataMap.GetString(Constant.MailTitle);
+            var content = context.JobDetail.JobDataMap.GetString(Constant.MailContent);
+            var mailTo = context.JobDetail.JobDataMap.GetString(Constant.MailTo);
+
+            LogInfo.Title = title;
+            LogInfo.Content = content;
+            LogInfo.MailTo = mailTo;
+
+            await MailHelper.SendMail(title, content, mailTo);
+
+            LogInfo.Result = "发送成功!";
+        }
+    }
+}

+ 12 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogMailModel.cs

@@ -0,0 +1,12 @@
+namespace Host.IJobs.Model
+{
+    public class LogMailModel : LogModel
+    {
+        public string Title { get; set; }
+        public string Content { get; set; }
+        /// <summary>
+        /// 收件邮箱
+        /// </summary>
+        public string MailTo { get; set; }
+    }
+}

+ 35 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogModel.cs

@@ -0,0 +1,35 @@
+using Newtonsoft.Json;
+
+namespace Host.IJobs.Model
+{
+    public abstract class LogModel
+    {
+        /// <summary>
+        /// 开始执行时间
+        /// </summary>
+        [JsonIgnore]
+        public string BeginTime { get; set; }
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        [JsonIgnore]
+        public string EndTime { get; set; }
+        /// <summary>
+        /// 耗时(秒)
+        /// </summary>
+        [JsonIgnore]
+        public string ExecuteTime { get; set; }
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string JobName { get; set; }
+        /// <summary>
+        /// 结果
+        /// </summary>
+        public string Result { get; set; }
+        /// <summary>
+        /// 异常消息
+        /// </summary>
+        public string ErrorMsg { get; set; }
+    }
+}

+ 8 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogMqttModel.cs

@@ -0,0 +1,8 @@
+namespace Host.IJobs.Model
+{
+    public class LogMqttModel : LogModel
+    {
+        public string Topic { get; set; }
+        public string Payload { get; set; }
+    }
+}

+ 8 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogRabbitModel.cs

@@ -0,0 +1,8 @@
+namespace Host.IJobs.Model
+{
+    public class LogRabbitModel : LogModel
+    {
+        public string RabbitQueue { get; set; }
+        public string RabbitBody { get; set; }
+    }
+}

+ 18 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/Model/LogUrlModel.cs

@@ -0,0 +1,18 @@
+namespace Host.IJobs.Model
+{
+    public class LogUrlModel : LogModel
+    {
+        /// <summary>
+        /// 请求地址
+        /// </summary>
+        public string Url { get; set; }
+        /// <summary>
+        /// 请求类型
+        /// </summary>
+        public string RequestType { get; set; }
+        /// <summary>
+        /// 请求参数
+        /// </summary>
+        public string Parameters { get; set; }
+    }
+}

+ 46 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/MqttJob.cs

@@ -0,0 +1,46 @@
+using Host.Common;
+using Host.IJobs.Model;
+using Host.Managers;
+using MQTTnet.Client.Publishing;
+using Newtonsoft.Json;
+using Quartz;
+using System.Threading.Tasks;
+
+namespace Host.IJobs
+{
+    public class MqttJob : JobBase<LogMqttModel>, IJob
+    {
+        private MqttManager mqttManager;
+        public MqttJob() : base(new LogMqttModel())
+        {
+            mqttManager = MqttManager.Instance;
+        }
+
+        public override async Task NextExecute(IJobExecutionContext context)
+        {
+            var topic = context.JobDetail.JobDataMap.GetString(Constant.Topic);
+            var payload = context.JobDetail.JobDataMap.GetString(Constant.Payload);
+            LogInfo.Topic = topic;
+            LogInfo.Payload = payload;
+
+            var mqttSet = await FileConfig.GetMqttSetAsync();
+            if (string.IsNullOrWhiteSpace(mqttSet.Host) || string.IsNullOrWhiteSpace(mqttSet.Port))
+                LogInfo.ErrorMsg = $"<span class='error'>请先在 [/seting] 页面配置MQTT设置。</span>";
+            else if (!mqttManager.MqttClient.IsConnected)
+                LogInfo.ErrorMsg = $"<span class='error'>Mqtt服务连接失败</span>";
+            else if (!mqttManager.MqttClient.IsStarted)
+                LogInfo.ErrorMsg = $"<span class='error'>Mqtt服务启动失败</span>";
+            else
+            {
+                var detectionrResult = await mqttManager.PublishAsync(topic, payload);
+                if (detectionrResult.ReasonCode != MqttClientPublishReasonCode.Success)
+                    LogInfo.ErrorMsg = $"<span class='error'>topic:{topic} reason:{detectionrResult.ReasonString} {detectionrResult.ReasonCode}</span>";
+            }
+
+            if (!string.IsNullOrWhiteSpace(LogInfo.ErrorMsg))
+                context.JobDetail.JobDataMap[Constant.EXCEPTION] = $"<div class='err-time'>{LogInfo.BeginTime}</div>{JsonConvert.SerializeObject(LogInfo)}";
+            else
+                LogInfo.Result = "发送成功!";
+        }
+    }
+}

+ 47 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/IJobs/RabbitJob.cs

@@ -0,0 +1,47 @@
+using Host.Common;
+using Host.IJobs.Model;
+using Host.Managers;
+using Quartz;
+using RabbitMQ.Client;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.IJobs
+{
+    public class RabbitJob : JobBase<LogRabbitModel>, IJob
+    {
+        private IConnection connection;
+        public RabbitJob() : base(new LogRabbitModel())
+        {
+            connection = RabbitMQManager.Instance.Connection;
+        }
+
+        public override async Task NextExecute(IJobExecutionContext context)
+        {
+            var queue = context.JobDetail.JobDataMap.GetString(Constant.RabbitQueue);
+            var body = context.JobDetail.JobDataMap.GetString(Constant.RabbitBody);
+            LogInfo.RabbitQueue = queue;
+            LogInfo.RabbitBody = body;
+
+            var rabbitSet = await FileConfig.GetRabbitSetAsync();
+            if (string.IsNullOrWhiteSpace(rabbitSet.RabbitHost) || string.IsNullOrWhiteSpace(rabbitSet.RabbitUserName))
+                LogInfo.ErrorMsg = $"<span class='error'>请先在 [/seting] 页面配置RabbitMQ设置。</span>";
+            else if (!connection?.IsOpen ?? true)
+                LogInfo.ErrorMsg = $"<span class='error'>RabbitMQ服务连接失败。</span>";
+            else
+            {
+                //创建通道
+                using (var channel = connection.CreateModel())
+                {
+                    //声明一个队列
+                    channel.QueueDeclare(queue, false, false, false, null);
+                    //发布消息
+                    channel.BasicPublish("", queue, null, Encoding.UTF8.GetBytes(body));
+                    channel.Close();
+                }
+
+                LogInfo.Result = "发送成功!";
+            }
+        }
+    }
+}

+ 103 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/MqttManager.cs

@@ -0,0 +1,103 @@
+using Host.Common;
+using Host.Common.Enums;
+using Host.Entity;
+using MQTTnet;
+using MQTTnet.Client;
+using MQTTnet.Client.Options;
+using MQTTnet.Client.Publishing;
+using MQTTnet.Extensions.ManagedClient;
+using MQTTnet.Protocol;
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Threading.Tasks;
+
+namespace Host.Managers
+{
+    /// <summary>
+    /// Mqtt - 单例
+    /// </summary>
+    public class MqttManager
+    {
+        public static readonly MqttManager Instance;
+        static MqttManager()
+        {
+            Instance = new MqttManager();
+        }
+
+        public IManagedMqttClient MqttClient { get; private set; }
+
+        /// <summary>
+        /// 重启启动
+        /// </summary>
+        /// <param name="model"></param>
+        /// <returns></returns>
+        public async Task RestartAsync()
+        {
+            try
+            {
+                await StopAsync();
+
+                var model = await FileConfig.GetMqttSetAsync();
+                MqttClient = new MqttFactory().CreateManagedMqttClient();
+                var mqttClientOptions = new MqttClientOptionsBuilder()
+                             .WithKeepAlivePeriod(TimeSpan.FromSeconds(29))
+                             .WithClientId(model.ClientId)
+                             .WithWebSocketServer($"{model.Host}:{model.Port}/mqtt")
+                             .WithCredentials(model.UserName, model.Password);
+
+                if (model.ConnectionMethod == ConnectionMethod.WSS)
+                    mqttClientOptions = mqttClientOptions.WithTls();
+
+                var options = new ManagedMqttClientOptionsBuilder()
+                       .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
+                       .WithClientOptions(mqttClientOptions.Build())
+                       .Build();
+
+                await MqttClient.StartAsync(options);
+            }
+            catch (Exception ex)
+            {
+                Log.Logger.Error($"MQTT启动异常,{ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 发布
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="topic"></param>
+        /// <param name="payloadData"></param>
+        /// <param name="retain"></param>
+        /// <param name="serviceLevel"></param>
+        /// <returns></returns>
+        public async Task<MqttClientPublishResult> PublishAsync<T>(string topic, T payloadData, bool retain = false, MqttQualityOfServiceLevel serviceLevel = MqttQualityOfServiceLevel.AtMostOnce) //where T : class, new()
+        {
+            var payload = JsonConvert.SerializeObject(payloadData, Formatting.None, AppSetting.SerializerSettings);
+            return await PublishAsync(topic, payload, retain);
+        }
+
+        /// <summary>
+        /// 发布
+        /// </summary>
+        /// <param name="topic"></param>
+        /// <param name="payload"></param>
+        /// <param name="retain"></param>
+        /// <param name="serviceLevel"></param>
+        /// <returns></returns>
+        public async Task<MqttClientPublishResult> PublishAsync(string topic, string payload, bool retain = false, MqttQualityOfServiceLevel serviceLevel = MqttQualityOfServiceLevel.AtMostOnce)
+        {
+            return await MqttClient.PublishAsync(topic, payload, serviceLevel, retain);
+        }
+
+        /// <summary>
+        /// Stop
+        /// </summary>
+        /// <returns></returns>
+        private async Task StopAsync()
+        {
+            if (MqttClient?.IsStarted ?? false)
+                await MqttClient?.StopAsync();
+        }
+    }
+}

+ 62 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/RabbitMQManager.cs

@@ -0,0 +1,62 @@
+using Host.Common;
+using RabbitMQ.Client;
+using System.Threading.Tasks;
+
+namespace Host.Managers
+{
+    public class RabbitMQManager
+    {
+        public static readonly RabbitMQManager Instance;
+        static RabbitMQManager()
+        {
+            Instance = new RabbitMQManager();
+        }
+
+
+        public IConnection Connection { get; private set; }
+
+        /// <summary>
+        /// 重启启动
+        /// </summary>
+        /// <param name="model"></param>
+        /// <returns></returns>
+        public async Task<bool> RestartAsync()
+        {
+            Stop();
+
+            var entity = await FileConfig.GetRabbitSetAsync();
+            //创建连接工厂
+            var factory = new ConnectionFactory
+            {
+                UserName = entity.RabbitUserName,//用户名
+                Password = entity.RabbitPassword,//密码
+                HostName = entity.RabbitHost,//rabbitmq ip
+                Port = entity.RabbitPort,
+            };
+            try
+            {
+                //创建连接
+                Connection = factory.CreateConnection();
+            }
+            catch (System.Exception ex)
+            {
+                //log
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Stop
+        /// </summary>
+        /// <returns></returns>
+        private void Stop()
+        {
+            if (Connection?.IsOpen ?? false)
+            {
+                Connection?.Close();
+                Connection?.Dispose();
+            }
+        }
+    }
+}

+ 617 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Managers/SchedulerCenter.cs

@@ -0,0 +1,617 @@
+using Host.Common;
+using Host.Common.Enums;
+using Host.Entity;
+using Host.IJobs;
+using Host.Repositories;
+using Microsoft.Extensions.Configuration;
+using Newtonsoft.Json;
+using Quartz;
+using Quartz.Impl;
+using Quartz.Impl.AdoJobStore;
+using Quartz.Impl.AdoJobStore.Common;
+using Quartz.Impl.Matchers;
+using Quartz.Impl.Triggers;
+using Quartz.Simpl;
+using Quartz.Util;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Talk.Extensions;
+
+namespace Host
+{
+    /// <summary>
+    /// 调度中心 [单例]
+    /// </summary>
+    public class SchedulerCenter
+    {
+        /// <summary>
+        /// 数据连接
+        /// </summary>
+        private IDbProvider dbProvider;
+        /// <summary>
+        /// ADO 数据类型
+        /// </summary>
+        private string driverDelegateType;
+
+        public SchedulerCenter()
+        {
+            InitDriverDelegateType();
+            dbProvider = new DbProvider(AppConfig.DbProviderName, AppConfig.ConnectionString);
+        }
+
+        /// <summary>
+        /// 初始化DriverDelegateType
+        /// </summary>
+        private void InitDriverDelegateType()
+        {
+            switch (AppConfig.DbProviderName)
+            {
+                case "SQLite-Microsoft":
+                case "SQLite":
+                    driverDelegateType = typeof(SQLiteDelegate).AssemblyQualifiedName;
+                    break;
+                case "MySql":
+                    driverDelegateType = typeof(MySQLDelegate).AssemblyQualifiedName;
+                    break;
+                case "OracleODPManaged":
+                    driverDelegateType = typeof(OracleDelegate).AssemblyQualifiedName;
+                    break;
+                case "SqlServer":
+                case "SQLServerMOT":
+                    driverDelegateType = typeof(SqlServerDelegate).AssemblyQualifiedName;
+                    break;
+                case "Npgsql":
+                    driverDelegateType = typeof(PostgreSQLDelegate).AssemblyQualifiedName;
+                    break;
+                case "Firebird":
+                    driverDelegateType = typeof(FirebirdDelegate).AssemblyQualifiedName;
+                    break;
+                default:
+                    throw new Exception("dbProviderName unreasonable");
+            }
+        }
+
+        /// <summary>
+        /// 初始化数据库表
+        /// </summary>
+        /// <returns></returns>
+        private async Task InitDBTableAsync()
+        {
+            //如果不存在sqlite数据库,则创建
+            //TODO 其他数据源...
+            if (driverDelegateType.Equals(typeof(SQLiteDelegate).AssemblyQualifiedName) ||
+                driverDelegateType.Equals(typeof(MySQLDelegate).AssemblyQualifiedName) ||
+                driverDelegateType.Equals(typeof(SqlServerDelegate).AssemblyQualifiedName) ||
+                driverDelegateType.Equals(typeof(PostgreSQLDelegate).AssemblyQualifiedName))
+            {
+                IRepositorie repositorie = RepositorieFactory.CreateRepositorie(driverDelegateType, dbProvider);
+                await repositorie?.InitTable();
+            }
+        }
+
+        /// <summary>
+        /// 调度器
+        /// </summary>
+        private IScheduler scheduler;
+
+        /// <summary>
+        /// 初始化Scheduler
+        /// </summary>
+        private async Task InitSchedulerAsync()
+        {
+            if (scheduler == null)
+            {
+                DBConnectionManager.Instance.AddConnectionProvider("default", dbProvider);
+                var serializer = new JsonObjectSerializer();
+                serializer.Initialize();
+                var jobStore = new JobStoreTX
+                {
+                    DataSource = "default",
+                    TablePrefix = "QRTZ_",
+                    InstanceId = "AUTO",
+                    DriverDelegateType = driverDelegateType,
+                    ObjectSerializer = serializer,
+                };
+                DirectSchedulerFactory.Instance.CreateScheduler("bennyScheduler", "AUTO", new DefaultThreadPool(), jobStore);
+                scheduler = await SchedulerRepository.Instance.Lookup("bennyScheduler");
+            }
+        }
+
+        /// <summary>
+        /// 开启调度器
+        /// </summary>
+        /// <returns></returns>
+        public async Task<bool> StartScheduleAsync()
+        {
+            //初始化数据库表结构
+            await InitDBTableAsync();
+            //初始化Scheduler
+            await InitSchedulerAsync();
+            //开启调度器
+            if (scheduler.InStandbyMode)
+            {
+                await scheduler.Start();
+                Log.Information("任务调度启动!");
+            }
+            return scheduler.InStandbyMode;
+        }
+
+        /// <summary>
+        /// 添加一个工作调度
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <param name="runNumber"></param>
+        /// <returns></returns>
+        public async Task<BaseResult> AddScheduleJobAsync(ScheduleEntity entity, long? runNumber = null)
+        {
+            var result = new BaseResult();
+            try
+            {
+                //检查任务是否已存在
+                var jobKey = new JobKey(entity.JobName, entity.JobGroup);
+                if (await scheduler.CheckExists(jobKey))
+                {
+                    result.Code = 500;
+                    result.Msg = "任务已存在";
+                    return result;
+                }
+                //http请求配置
+                var httpDir = new Dictionary<string, string>()
+                {
+                    { Constant.EndAt, entity.EndTime.ToString()},
+                    { Constant.JobTypeEnum, ((int)entity.JobType).ToString()},
+                    { Constant.MAILMESSAGE, ((int)entity.MailMessage).ToString()},
+                };
+                if (runNumber.HasValue)
+                    httpDir.Add(Constant.RUNNUMBER, runNumber.ToString());
+
+                IJobConfigurator jobConfigurator = null;
+                if (entity.JobType == JobTypeEnum.Url)
+                {
+                    jobConfigurator = JobBuilder.Create<HttpJob>();
+                    httpDir.Add(Constant.REQUESTURL, entity.RequestUrl);
+                    httpDir.Add(Constant.HEADERS, entity.Headers);
+                    httpDir.Add(Constant.REQUESTPARAMETERS, entity.RequestParameters);
+                    httpDir.Add(Constant.REQUESTTYPE, ((int)entity.RequestType).ToString());
+                }
+                else if (entity.JobType == JobTypeEnum.Emial)
+                {
+                    jobConfigurator = JobBuilder.Create<MailJob>();
+                    httpDir.Add(Constant.MailTitle, entity.MailTitle);
+                    httpDir.Add(Constant.MailContent, entity.MailContent);
+                    httpDir.Add(Constant.MailTo, entity.MailTo);
+                }
+                else if (entity.JobType == JobTypeEnum.Mqtt)
+                {
+                    jobConfigurator = JobBuilder.Create<MqttJob>();
+                    httpDir.Add(Constant.Topic, entity.Topic);
+                    httpDir.Add(Constant.Payload, entity.Payload);
+                }
+                else if (entity.JobType == JobTypeEnum.RabbitMQ)
+                {
+                    jobConfigurator = JobBuilder.Create<RabbitJob>();
+                    httpDir.Add(Constant.RabbitQueue, entity.RabbitQueue);
+                    httpDir.Add(Constant.RabbitBody, entity.RabbitBody);
+                }
+
+                // 定义这个工作,并将其绑定到我们的IJob实现类                
+                IJobDetail job = jobConfigurator
+                    .SetJobData(new JobDataMap(httpDir))
+                    .WithDescription(entity.Description)
+                    .WithIdentity(entity.JobName, entity.JobGroup)
+                    .Build();
+                // 创建触发器
+                ITrigger trigger;
+                //校验是否正确的执行周期表达式
+                if (entity.TriggerType == TriggerTypeEnum.Cron)//CronExpression.IsValidExpression(entity.Cron))
+                {
+                    trigger = CreateCronTrigger(entity);
+                }
+                else
+                {
+                    trigger = CreateSimpleTrigger(entity);
+                }
+
+                // 告诉Quartz使用我们的触发器来安排作业
+                await scheduler.ScheduleJob(job, trigger);
+                result.Code = 200;
+            }
+            catch (Exception ex)
+            {
+                result.Code = 505;
+                result.Msg = ex.Message;
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 暂停/删除 指定的计划
+        /// </summary>
+        /// <param name="jobGroup">任务分组</param>
+        /// <param name="jobName">任务名称</param>
+        /// <param name="isDelete">停止并删除任务</param>
+        /// <returns></returns>
+        public async Task<BaseResult> StopOrDelScheduleJobAsync(string jobGroup, string jobName, bool isDelete = false)
+        {
+            BaseResult result;
+            try
+            {
+                await scheduler.PauseJob(new JobKey(jobName, jobGroup));
+                if (isDelete)
+                {
+                    await scheduler.DeleteJob(new JobKey(jobName, jobGroup));
+                    result = new BaseResult
+                    {
+                        Code = 200,
+                        Msg = "删除任务计划成功!"
+                    };
+                }
+                else
+                {
+                    result = new BaseResult
+                    {
+                        Code = 200,
+                        Msg = "停止任务计划成功!"
+                    };
+                }
+
+            }
+            catch (Exception ex)
+            {
+                result = new BaseResult
+                {
+                    Code = 505,
+                    Msg = "停止任务计划失败" + ex.Message
+                };
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 恢复运行暂停的任务
+        /// </summary>
+        /// <param name="jobName">任务名称</param>
+        /// <param name="jobGroup">任务分组</param>
+        public async Task<BaseResult> ResumeJobAsync(string jobGroup, string jobName)
+        {
+            BaseResult result = new BaseResult();
+            try
+            {
+                //检查任务是否存在
+                var jobKey = new JobKey(jobName, jobGroup);
+                if (await scheduler.CheckExists(jobKey))
+                {
+                    var jobDetail = await scheduler.GetJobDetail(jobKey);
+                    var endTime = jobDetail.JobDataMap.GetString("EndAt");
+                    if (!string.IsNullOrWhiteSpace(endTime) && DateTime.Parse(endTime) <= DateTime.Now)
+                    {
+                        result.Code = 500;
+                        result.Msg = "Job的结束时间已过期。";
+                    }
+                    else
+                    {
+                        //任务已经存在则暂停任务
+                        await scheduler.ResumeJob(jobKey);
+                        result.Msg = "恢复任务计划成功!";
+                        Log.Information(string.Format("任务“{0}”恢复运行", jobName));
+                    }
+                }
+                else
+                {
+                    result.Code = 500;
+                    result.Msg = "任务不存在";
+                }
+            }
+            catch (Exception ex)
+            {
+                result.Msg = "恢复任务计划失败!";
+                result.Code = 500;
+                Log.Error(string.Format("恢复任务失败!{0}", ex));
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 查询任务
+        /// </summary>
+        /// <param name="jobGroup"></param>
+        /// <param name="jobName"></param>
+        /// <returns></returns>
+        public async Task<ScheduleEntity> QueryJobAsync(string jobGroup, string jobName)
+        {
+            var entity = new ScheduleEntity();
+            var jobKey = new JobKey(jobName, jobGroup);
+            var jobDetail = await scheduler.GetJobDetail(jobKey);
+            var triggersList = await scheduler.GetTriggersOfJob(jobKey);
+            var triggers = triggersList.AsEnumerable().FirstOrDefault();
+            var intervalSeconds = (triggers as SimpleTriggerImpl)?.RepeatInterval.TotalSeconds;
+            var endTime = jobDetail.JobDataMap.GetString("EndAt");
+            entity.BeginTime = triggers.StartTimeUtc.LocalDateTime;
+            if (!string.IsNullOrWhiteSpace(endTime)) entity.EndTime = DateTime.Parse(endTime);
+            if (intervalSeconds.HasValue) entity.IntervalSecond = Convert.ToInt32(intervalSeconds.Value);
+            entity.JobGroup = jobGroup;
+            entity.JobName = jobName;
+            entity.Cron = (triggers as CronTriggerImpl)?.CronExpressionString;
+            entity.RunTimes = (triggers as SimpleTriggerImpl)?.RepeatCount;
+            entity.TriggerType = triggers is SimpleTriggerImpl ? TriggerTypeEnum.Simple : TriggerTypeEnum.Cron;
+            entity.MailMessage = (MailMessageEnum)int.Parse(jobDetail.JobDataMap.GetString(Constant.MAILMESSAGE) ?? "0");
+            entity.Description = jobDetail.Description;
+            //旧代码没有保存JobTypeEnum,所以None可以默认为Url。
+            entity.JobType = (JobTypeEnum)int.Parse(jobDetail.JobDataMap.GetString(Constant.JobTypeEnum) ?? "1");
+
+            switch (entity.JobType)
+            {
+                case JobTypeEnum.None:
+                    break;
+                case JobTypeEnum.Url:
+                    entity.RequestUrl = jobDetail.JobDataMap.GetString(Constant.REQUESTURL);
+                    entity.RequestType = (RequestTypeEnum)int.Parse(jobDetail.JobDataMap.GetString(Constant.REQUESTTYPE));
+                    entity.RequestParameters = jobDetail.JobDataMap.GetString(Constant.REQUESTPARAMETERS);
+                    entity.Headers = jobDetail.JobDataMap.GetString(Constant.HEADERS);
+                    break;
+                case JobTypeEnum.Emial:
+                    entity.MailTitle = jobDetail.JobDataMap.GetString(Constant.MailTitle);
+                    entity.MailContent = jobDetail.JobDataMap.GetString(Constant.MailContent);
+                    entity.MailTo = jobDetail.JobDataMap.GetString(Constant.MailTo);
+                    break;
+                case JobTypeEnum.Mqtt:
+                    entity.Payload = jobDetail.JobDataMap.GetString(Constant.Payload);
+                    entity.Topic = jobDetail.JobDataMap.GetString(Constant.Topic);
+                    break;
+                case JobTypeEnum.RabbitMQ:
+                    entity.RabbitQueue = jobDetail.JobDataMap.GetString(Constant.RabbitQueue);
+                    entity.RabbitBody = jobDetail.JobDataMap.GetString(Constant.RabbitBody);
+                    break;
+                case JobTypeEnum.Hotreload:
+                    break;
+                default:
+                    break;
+            }
+            return entity;
+        }
+
+        /// <summary>
+        /// 立即执行
+        /// </summary>
+        /// <param name="jobKey"></param>
+        /// <returns></returns>
+        public async Task<bool> TriggerJobAsync(JobKey jobKey)
+        {
+            await scheduler.TriggerJob(jobKey);
+            return true;
+        }
+
+        /// <summary>
+        /// 获取job日志
+        /// </summary>
+        /// <param name="jobKey"></param>
+        /// <returns></returns>
+        public async Task<List<string>> GetJobLogsAsync(JobKey jobKey)
+        {
+            var jobDetail = await scheduler.GetJobDetail(jobKey);
+            return jobDetail.JobDataMap[Constant.LOGLIST] as List<string>;
+        }
+
+        /// <summary>
+        /// 获取运行次数
+        /// </summary>
+        /// <param name="jobKey"></param>
+        /// <returns></returns>
+        public async Task<long> GetRunNumberAsync(JobKey jobKey)
+        {
+            var jobDetail = await scheduler.GetJobDetail(jobKey);
+            return jobDetail.JobDataMap.GetLong(Constant.RUNNUMBER);
+        }
+
+        /// <summary>
+        /// 获取所有Job(详情信息 - 初始化页面调用)
+        /// </summary>
+        /// <returns></returns>
+        public async Task<List<JobInfoEntity>> GetAllJobAsync()
+        {
+            List<JobKey> jboKeyList = new List<JobKey>();
+            List<JobInfoEntity> jobInfoList = new List<JobInfoEntity>();
+            var groupNames = await scheduler.GetJobGroupNames();
+            foreach (var groupName in groupNames.OrderBy(t => t))
+            {
+                jboKeyList.AddRange(await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)));
+                jobInfoList.Add(new JobInfoEntity() { GroupName = groupName });
+            }
+            foreach (var jobKey in jboKeyList.OrderBy(t => t.Name))
+            {
+                var jobDetail = await scheduler.GetJobDetail(jobKey);
+                var triggersList = await scheduler.GetTriggersOfJob(jobKey);
+                var triggers = triggersList.AsEnumerable().FirstOrDefault();
+
+                var interval = string.Empty;
+                if (triggers is SimpleTriggerImpl)
+                    interval = (triggers as SimpleTriggerImpl)?.RepeatInterval.ToString();
+                else
+                    interval = (triggers as CronTriggerImpl)?.CronExpressionString;
+
+                foreach (var jobInfo in jobInfoList)
+                {
+                    if (jobInfo.GroupName == jobKey.Group)
+                    {
+                        //旧代码没有保存JobTypeEnum,所以None可以默认为Url。
+                        var jobType = (JobTypeEnum)jobDetail.JobDataMap.GetLong(Constant.JobTypeEnum);
+                        jobType = jobType == JobTypeEnum.None ? JobTypeEnum.Url : jobType;
+
+                        var triggerAddress = string.Empty;
+                        if (jobType == JobTypeEnum.Url)
+                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.REQUESTURL);
+                        else if (jobType == JobTypeEnum.Emial)
+                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.MailTo);
+                        else if (jobType == JobTypeEnum.Mqtt)
+                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.Topic);
+                        else if (jobType == JobTypeEnum.RabbitMQ)
+                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.RabbitQueue);
+
+                        //Constant.MailTo
+                        jobInfo.JobInfoList.Add(new JobInfo()
+                        {
+                            Name = jobKey.Name,
+                            LastErrMsg = jobDetail.JobDataMap.GetString(Constant.EXCEPTION),
+                            TriggerAddress = triggerAddress,
+                            TriggerState = await scheduler.GetTriggerState(triggers.Key),
+                            PreviousFireTime = triggers.GetPreviousFireTimeUtc()?.LocalDateTime,
+                            NextFireTime = triggers.GetNextFireTimeUtc()?.LocalDateTime,
+                            BeginTime = triggers.StartTimeUtc.LocalDateTime,
+                            Interval = interval,
+                            EndTime = triggers.EndTimeUtc?.LocalDateTime,
+                            Description = jobDetail.Description,
+                            RequestType = jobDetail.JobDataMap.GetString(Constant.REQUESTTYPE),
+                            RunNumber = jobDetail.JobDataMap.GetLong(Constant.RUNNUMBER),
+                            JobType = (long)jobType
+                            //(triggers as SimpleTriggerImpl)?.TimesTriggered
+                            //CronTriggerImpl 中没有 TimesTriggered 所以自己RUNNUMBER记录
+                        });
+                        continue;
+                    }
+                }
+            }
+            return jobInfoList;
+        }
+
+        /// <summary>
+        /// 移除异常信息
+        /// 因为只能在IJob持久化操作JobDataMap,所有这里直接暴力操作数据库。
+        /// </summary>
+        /// <param name="jobGroup"></param>
+        /// <param name="jobName"></param>
+        /// <returns></returns>          
+        public async Task<bool> RemoveErrLog(string jobGroup, string jobName)
+        {
+            IRepositorie logRepositorie = RepositorieFactory.CreateRepositorie(driverDelegateType, dbProvider);
+
+            if (logRepositorie == null) return false;
+
+            await logRepositorie.RemoveErrLogAsync(jobGroup, jobName);
+
+            var jobKey = new JobKey(jobName, jobGroup);
+            var jobDetail = await scheduler.GetJobDetail(jobKey);
+            jobDetail.JobDataMap[Constant.EXCEPTION] = string.Empty;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 获取所有Job信息(简要信息 - 刷新数据的时候使用)
+        /// </summary>
+        /// <returns></returns>
+        public async Task<List<JobBriefInfoEntity>> GetAllJobBriefInfoAsync()
+        {
+            List<JobKey> jboKeyList = new List<JobKey>();
+            List<JobBriefInfoEntity> jobInfoList = new List<JobBriefInfoEntity>();
+            var groupNames = await scheduler.GetJobGroupNames();
+            foreach (var groupName in groupNames.OrderBy(t => t))
+            {
+                jboKeyList.AddRange(await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)));
+                jobInfoList.Add(new JobBriefInfoEntity() { GroupName = groupName });
+            }
+            foreach (var jobKey in jboKeyList.OrderBy(t => t.Name))
+            {
+                var jobDetail = await scheduler.GetJobDetail(jobKey);
+                var triggersList = await scheduler.GetTriggersOfJob(jobKey);
+                var triggers = triggersList.AsEnumerable().FirstOrDefault();
+
+                foreach (var jobInfo in jobInfoList)
+                {
+                    if (jobInfo.GroupName == jobKey.Group)
+                    {
+                        jobInfo.JobInfoList.Add(new JobBriefInfo()
+                        {
+                            Name = jobKey.Name,
+                            LastErrMsg = jobDetail?.JobDataMap.GetString(Constant.EXCEPTION),
+                            TriggerState = await scheduler.GetTriggerState(triggers.Key),
+                            PreviousFireTime = triggers.GetPreviousFireTimeUtc()?.LocalDateTime,
+                            NextFireTime = triggers.GetNextFireTimeUtc()?.LocalDateTime,
+                            RunNumber = jobDetail?.JobDataMap.GetLong(Constant.RUNNUMBER) ?? 0
+                        });
+                        continue;
+                    }
+                }
+            }
+            return jobInfoList;
+        }
+
+        /// <summary>
+        /// 停止任务调度
+        /// </summary>
+        public async Task<bool> StopScheduleAsync()
+        {
+            //判断调度是否已经关闭
+            if (!scheduler.InStandbyMode)
+            {
+                //等待任务运行完成
+                await scheduler.Standby(); //TODO  注意:Shutdown后Start会报错,所以这里使用暂停。
+                Log.Information("任务调度暂停!");
+            }
+            return !scheduler.InStandbyMode;
+        }
+
+        /// <summary>
+        /// 创建类型Simple的触发器
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        private ITrigger CreateSimpleTrigger(ScheduleEntity entity)
+        {
+            //作业触发器
+            if (entity.RunTimes.HasValue && entity.RunTimes > 0)
+            {
+                return TriggerBuilder.Create()
+               .WithIdentity(entity.JobName, entity.JobGroup)
+               .StartAt(entity.BeginTime)//开始时间
+                                         //.EndAt(entity.EndTime)//结束数据
+               .WithSimpleSchedule(x =>
+               {
+                   x.WithIntervalInSeconds(entity.IntervalSecond.Value)//执行时间间隔,单位秒
+                        .WithRepeatCount(entity.RunTimes.Value)//执行次数、默认从0开始
+                        .WithMisfireHandlingInstructionFireNow();
+               })
+               .ForJob(entity.JobName, entity.JobGroup)//作业名称
+               .Build();
+            }
+            else
+            {
+                return TriggerBuilder.Create()
+               .WithIdentity(entity.JobName, entity.JobGroup)
+               .StartAt(entity.BeginTime)//开始时间
+                                         //.EndAt(entity.EndTime)//结束数据
+               .WithSimpleSchedule(x =>
+               {
+                   x.WithIntervalInSeconds(entity.IntervalSecond.Value)//执行时间间隔,单位秒
+                        .RepeatForever()//无限循环
+                        .WithMisfireHandlingInstructionFireNow();
+               })
+               .ForJob(entity.JobName, entity.JobGroup)//作业名称
+               .Build();
+            }
+
+        }
+
+        /// <summary>
+        /// 创建类型Cron的触发器
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        private ITrigger CreateCronTrigger(ScheduleEntity entity)
+        {
+            // 作业触发器
+            return TriggerBuilder.Create()
+
+                   .WithIdentity(entity.JobName, entity.JobGroup)
+                   .StartAt(entity.BeginTime)//开始时间
+                                             //.EndAt(entity.EndTime)//结束时间
+                   .WithCronSchedule(entity.Cron, cronScheduleBuilder => cronScheduleBuilder.WithMisfireHandlingInstructionFireAndProceed())//指定cron表达式
+                   .ForJob(entity.JobName, entity.JobGroup)//作业名称
+                   .Build();
+        }
+
+    }
+}
+

+ 17 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Model/HttpResultModel.cs

@@ -0,0 +1,17 @@
+namespace Host.Model
+{
+    /// <summary>
+    /// Job任务结果
+    /// </summary>
+    public class HttpResultModel
+    {
+        /// <summary>
+        /// 请求是否成功
+        /// </summary>
+        public bool IsSuccess { get; set; } = true;
+        /// <summary>
+        /// 异常消息
+        /// </summary>
+        public string ErrorMsg { get; set; }
+    }
+}

+ 44 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Model/LogInfoModel.cs

@@ -0,0 +1,44 @@
+using System;
+
+namespace Host.Model
+{
+    public class LogInfoModel
+    {
+        /// <summary>
+        /// 开始执行时间
+        /// </summary>
+        public string BeginTime { get; set; }
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public string EndTime { get; set; }
+        /// <summary>
+        /// 耗时(秒)
+        /// </summary>
+        public string ExecuteTime { get; set; }
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string JobName { get; set; }
+        /// <summary>
+        /// 请求地址
+        /// </summary>
+        public string Url { get; set; }
+        /// <summary>
+        /// 请求类型
+        /// </summary>
+        public string RequestType { get; set; }
+        /// <summary>
+        /// 请求参数
+        /// </summary>
+        public string Parameters { get; set; }
+        /// <summary>
+        /// 请求结果
+        /// </summary>
+        public string Result { get; set; }
+        /// <summary>
+        /// 异常消息
+        /// </summary>
+        public string ErrorMsg { get; set; }
+    }
+}

+ 11 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Model/SendMailModel.cs

@@ -0,0 +1,11 @@
+using Host.Entity;
+
+namespace Host.Model
+{
+    public class SendMailModel
+    {
+        public string Title { get; set; }
+        public string Content { get; set; }
+        public MailEntity MailInfo { get; set; } = null;
+    }
+}

+ 20 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Program.cs

@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+
+namespace Host
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateHostBuilder(args).Build().Run();
+        }
+
+        public static IHostBuilder CreateHostBuilder(string[] args) =>
+                Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
+                .ConfigureWebHostDefaults(webBuilder =>
+                {
+                    webBuilder.UseStartup<Startup>();
+                });
+    }
+}

+ 19 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+此文件由 Web 项目的发布/打包过程使用。可以通过编辑此 MSBuild 文件
+自定义此过程的行为。为了解与此相关的更多内容,请访问 https://go.microsoft.com/fwlink/?LinkID=208121。 
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <WebPublishMethod>FileSystem</WebPublishMethod>
+    <PublishProvider>FileSystem</PublishProvider>
+    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
+    <LastUsedPlatform>Any CPU</LastUsedPlatform>
+    <SiteUrlToLaunchAfterPublish />
+    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
+    <ExcludeApp_Data>False</ExcludeApp_Data>
+    <ProjectGuid>62c51804-d792-491e-82e6-ff6fbae2983c</ProjectGuid>
+    <publishUrl>D:\Users\benny\Desktop\quartzUI</publishUrl>
+    <DeleteExistingFiles>False</DeleteExistingFiles>
+  </PropertyGroup>
+</Project>

+ 11 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/PublishProfiles/FolderProfile.pubxml.user

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+此文件由 Web 项目的发布/打包过程使用。可以通过编辑此 MSBuild 文件
+自定义此过程的行为。为了解与此相关的更多内容,请访问 https://go.microsoft.com/fwlink/?LinkID=208121。 
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <TimeStampOfAssociatedLegacyPublishXmlFile />
+    <_PublishTargetUrl>D:\Users\benny\Desktop\quartzUI</_PublishTargetUrl>
+  </PropertyGroup>
+</Project>

+ 12 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Properties/launchSettings.json

@@ -0,0 +1,12 @@
+{
+  "profiles": {
+    "Host": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      },
+      "applicationUrl": "http://localhost:8100/"
+    }
+  }
+}

+ 17 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/IRepositorie.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public interface IRepositorie
+    {
+        /// <summary>
+        /// 初始化表结构
+        /// </summary>
+        /// <returns></returns>
+        Task<int> InitTable();
+        Task<bool> RemoveErrLogAsync(string jobGroup, string jobName);
+    }
+}

+ 241 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/OracleDynamicParameters.cs

@@ -0,0 +1,241 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using Dapper;
+using Oracle.ManagedDataAccess.Client;
+
+namespace Host.Repositories
+{
+    internal class OracleDynamicParameters
+    {
+        private static Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>();
+
+        private Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
+        private List<object> templates;
+
+        private class ParamInfo
+        {
+
+            public string Name { get; set; }
+
+            public object Value { get; set; }
+
+            public ParameterDirection ParameterDirection { get; set; }
+
+            public OracleDbType? DbType { get; set; }
+
+            public int? Size { get; set; }
+
+            public IDbDataParameter AttachedParam { get; set; }
+        }
+
+        /// <summary>
+        /// construct a dynamic parameter bag
+        /// </summary>
+        public OracleDynamicParameters()
+        {
+        }
+
+        /// <summary>
+        /// construct a dynamic parameter bag
+        /// </summary>
+        /// <param name="template">can be an anonymous type or a DynamicParameters bag</param>
+        public OracleDynamicParameters(object template)
+        {
+            AddDynamicParams(template);
+        }
+
+        /// <summary>
+        /// Append a whole object full of params to the dynamic
+        /// EG: AddDynamicParams(new {A = 1, B = 2}) // will add property A and B to the dynamic
+        /// </summary>
+        /// <param name="param"></param>
+        public void AddDynamicParams(
+#if CSHARP30
+        			object param
+#else
+        dynamic param
+#endif
+        )
+        {
+            var obj = param as object;
+            if (obj != null)
+            {
+                var subDynamic = obj as OracleDynamicParameters;
+                if (subDynamic == null)
+                {
+                    var dictionary = obj as IEnumerable<KeyValuePair<string, object>>;
+                    if (dictionary == null)
+                    {
+                        templates = templates ?? new List<object>();
+                        templates.Add(obj);
+                    }
+                    else
+                    {
+                        foreach (var kvp in dictionary)
+                        {
+#if CSHARP30
+        							Add(kvp.Key, kvp.Value, null, null, null);
+#else
+                            Add(kvp.Key, kvp.Value);
+#endif
+                        }
+                    }
+                }
+                else
+                {
+                    if (subDynamic.parameters != null)
+                    {
+                        foreach (var kvp in subDynamic.parameters)
+                        {
+                            parameters.Add(kvp.Key, kvp.Value);
+                        }
+                    }
+
+                    if (subDynamic.templates != null)
+                    {
+                        templates = templates ?? new List<object>();
+                        foreach (var t in subDynamic.templates)
+                        {
+                            templates.Add(t);
+                        }
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Add a parameter to this dynamic parameter list
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
+        /// <param name="dbType"></param>
+        /// <param name="direction"></param>
+        /// <param name="size"></param>
+        public void Add(
+#if CSHARP30
+        			string name, object value, DbType? dbType, ParameterDirection? direction, int? size
+#else
+        string name, object value = null, OracleDbType? dbType = null, ParameterDirection? direction = null, int? size = null
+#endif
+        )
+        {
+            parameters[Clean(name)] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size };
+        }
+
+        private static string Clean(string name)
+        {
+            if (!string.IsNullOrEmpty(name))
+            {
+                switch (name[0])
+                {
+                    case '@':
+                    case ':':
+                    case '?':
+                        return name.Substring(1);
+                }
+            }
+            return name;
+        }
+
+        /// <summary>
+        /// Add all the parameters needed to the command just before it executes
+        /// </summary>
+        /// <param name="command">The raw command prior to execution</param>
+        /// <param name="identity">Information about the query</param>
+        protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
+        {
+            if (templates != null)
+            {
+                foreach (var template in templates)
+                {
+                    var newIdent = identity.ForDynamicParameters(template.GetType());
+                    Action<IDbCommand, object> appender;
+
+                    lock (paramReaderCache)
+                    {
+                        if (!paramReaderCache.TryGetValue(newIdent, out appender))
+                        {
+                            appender = SqlMapper.CreateParamInfoGenerator(newIdent, false, false);
+                            paramReaderCache[newIdent] = appender;
+                        }
+                    }
+
+                    appender(command, template);
+                }
+            }
+
+            foreach (var param in parameters.Values)
+            {
+                string name = Clean(param.Name);
+                bool add = !((OracleCommand)command).Parameters.Contains(name);
+                OracleParameter p;
+                if (add)
+                {
+                    p = ((OracleCommand)command).CreateParameter();
+                    p.ParameterName = name;
+                }
+                else
+                {
+                    p = ((OracleCommand)command).Parameters[name];
+                }
+                var val = param.Value;
+                p.Value = val ?? DBNull.Value;
+                p.Direction = param.ParameterDirection;
+                var s = val as string;
+                if (s != null)
+                {
+                    if (s.Length <= 4000)
+                    {
+                        p.Size = 4000;
+                    }
+                }
+                if (param.Size != null)
+                {
+                    p.Size = param.Size.Value;
+                }
+                if (param.DbType != null)
+                {
+                    p.OracleDbType = param.DbType.Value;
+                }
+                if (add)
+                {
+                    command.Parameters.Add(p);
+                }
+                param.AttachedParam = p;
+            }
+        }
+
+        /// <summary>
+        /// All the names of the param in the bag, use Get to yank them out
+        /// </summary>
+        public IEnumerable<string> ParameterNames
+        {
+            get
+            {
+                return parameters.Select(p => p.Key);
+            }
+        }
+
+        /// <summary>
+        /// Get the value of a parameter
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="name"></param>
+        /// <returns>The value, note DBNull.Value is not returned, instead the value is returned as null</returns>
+        public T Get<T>(string name)
+        {
+            var val = parameters[Clean(name)].AttachedParam.Value;
+            if (val == DBNull.Value)
+            {
+                if (default(T) != null)
+                {
+                    throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!");
+                }
+                return default(T);
+            }
+            return (T)val;
+        }
+    }
+}

+ 37 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieFactory.cs

@@ -0,0 +1,37 @@
+using Quartz.Impl.AdoJobStore;
+using Quartz.Impl.AdoJobStore.Common;
+
+namespace Host.Repositories
+{
+    public class RepositorieFactory
+    {
+        public static IRepositorie CreateRepositorie(string driverDelegateType, IDbProvider dbProvider)
+        {
+
+            if (driverDelegateType == typeof(SQLiteDelegate).AssemblyQualifiedName)
+            {
+                return new RepositorieSQLite(dbProvider);
+            }
+            else if (driverDelegateType == typeof(MySQLDelegate).AssemblyQualifiedName)
+            {
+                return new RepositorieMySql(dbProvider);
+            }
+            else if (driverDelegateType == typeof(PostgreSQLDelegate).AssemblyQualifiedName)
+            {
+                return new RepositoriePostgreSQL(dbProvider);
+            }
+            else if (driverDelegateType == typeof(OracleDelegate).AssemblyQualifiedName)
+            {
+                return new RepositorieOracle(dbProvider);
+            }
+            else if (driverDelegateType == typeof(SqlServerDelegate).AssemblyQualifiedName)
+            {
+                return new RepositorieSqlServer(dbProvider);
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+}

+ 87 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieMySql.cs

@@ -0,0 +1,87 @@
+using Dapper;
+using Host.Common;
+using MySql.Data.MySqlClient;
+using Newtonsoft.Json.Linq;
+using Quartz.Impl.AdoJobStore.Common;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public class RepositorieMySql : IRepositorie
+    {
+        private IDbProvider DBProvider { get; }
+        public RepositorieMySql(IDbProvider dbProvider)
+        {
+            DBProvider = dbProvider;
+        }
+
+        public async Task<int> InitTable()
+        {
+            using (var connection = new MySqlConnection(DBProvider.ConnectionString))
+            {
+                var check_sql = @"SELECT
+	                                        COUNT(1)
+                                        FROM
+	                                        information_schema. TABLES
+                                        WHERE
+	                                        table_name IN (
+		                                        'QRTZ_BLOB_TRIGGERS',
+		                                        'QRTZ_CALENDARS',
+		                                        'QRTZ_CRON_TRIGGERS',
+		                                        'QRTZ_FIRED_TRIGGERS',
+		                                        'QRTZ_JOB_DETAILS',
+		                                        'QRTZ_LOCKS',
+		                                        'QRTZ_PAUSED_TRIGGER_GRPS',
+		                                        'QRTZ_SCHEDULER_STATE',
+		                                        'QRTZ_SIMPLE_TRIGGERS',
+		                                        'QRTZ_SIMPROP_TRIGGERS',
+		                                        'QRTZ_TRIGGERS'
+	                                        );";
+                var count = await connection.QueryFirstOrDefaultAsync<int>(check_sql);
+                //初始化 建表
+                if (count == 0)
+                {
+                    string init_sql = await File.ReadAllTextAsync("Tables/tables_mysql_innodb.sql");
+                    return await connection.ExecuteAsync(init_sql);
+                }
+            }
+            return 0;
+        }
+
+        public async Task<bool> RemoveErrLogAsync(string jobGroup, string jobName)
+        {
+            try
+            {
+                using (var connection = new MySqlConnection(DBProvider.ConnectionString))
+                {
+                    string sql = $@"SELECT
+	                                JOB_DATA
+                                FROM
+	                                QRTZ_JOB_DETAILS
+                                WHERE
+	                                JOB_NAME = @jobName
+                                AND JOB_GROUP = @jobGroup";
+
+                    var byteArray = await connection.ExecuteScalarAsync<byte[]>(sql, new { jobName, jobGroup });
+                    var jsonStr = Encoding.Default.GetString(byteArray);
+                    JObject source = JObject.Parse(jsonStr);
+                    source.Remove("Exception");//移除异常日志 
+                    var modifySql = $@"UPDATE QRTZ_JOB_DETAILS
+                                    SET JOB_DATA = @jobData
+                                    WHERE
+	                                    JOB_NAME = @jobName
+                                    AND JOB_GROUP = @jobGroup";
+                    await connection.ExecuteAsync(modifySql, new { jobName, jobGroup, jobData = source.ToString() });
+                }
+
+                return true;
+            }
+            catch
+            {
+                return false;
+            }
+        }
+    }
+}

+ 59 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieOracle.cs

@@ -0,0 +1,59 @@
+using Dapper;
+using Newtonsoft.Json.Linq;
+using Oracle.ManagedDataAccess.Client;
+using Quartz.Impl.AdoJobStore.Common;
+using System;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public class RepositorieOracle : IRepositorie
+    {
+        private IDbProvider DBProvider { get; }
+
+        public RepositorieOracle(IDbProvider dbProvider)
+        {
+            DBProvider = dbProvider;
+        }
+
+        public async Task<bool> RemoveErrLogAsync(string jobGroup, string jobName)
+        {
+            try
+            {
+                using (var connection = new OracleConnection(DBProvider.ConnectionString))
+                {
+                    string sql = $@"SELECT
+	                                JOB_DATA
+                                FROM
+	                                QRTZ_JOB_DETAILS
+                                WHERE
+	                                JOB_NAME = :jobName
+                                AND JOB_GROUP = :jobGroup";
+
+                    var byteArray = await connection.ExecuteScalarAsync<byte[]>(sql, new { jobName, jobGroup });
+                    var jsonStr = Encoding.UTF8.GetString(byteArray);
+                    JObject source = JObject.Parse(jsonStr);
+                    source.Remove("Exception");//移除异常日志 
+                    var modifySql = $@"UPDATE QRTZ_JOB_DETAILS
+                                    SET JOB_DATA = :jobData
+                                    WHERE
+	                                    JOB_NAME = :jobName
+                                    AND JOB_GROUP = :jobGroup";
+                    await connection.ExecuteAsync(modifySql, new { jobName, jobGroup, jobData = Encoding.UTF8.GetBytes(source.ToString()) });
+                }
+                return true;
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
+        }
+
+        public Task<int> InitTable()
+        {
+            //TODO 待实现...
+            return Task.FromResult(-1);
+        }
+    }
+}

+ 88 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositoriePostgreSQL.cs

@@ -0,0 +1,88 @@
+using Dapper;
+using Host.Common;
+using Newtonsoft.Json.Linq;
+using Npgsql;
+using Quartz.Impl.AdoJobStore.Common;
+using System;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public class RepositoriePostgreSQL : IRepositorie
+    {
+        private IDbProvider DBProvider { get; }
+        public RepositoriePostgreSQL(IDbProvider dbProvider)
+        {
+            DBProvider = dbProvider;
+        }
+
+        public async Task<int> InitTable()
+        {
+            using (var connection = new NpgsqlConnection(DBProvider.ConnectionString))
+            {
+                var check_sql = @"SELECT
+	                                        COUNT (1)
+                                        FROM
+	                                        pg_class
+                                        WHERE
+	                                        relname IN (
+		                                        'qrtz_blob_triggers',
+		                                        'qrtz_calendars',
+		                                        'qrtz_cron_triggers',
+		                                        'qrtz_fired_triggers',
+		                                        'qrtz_job_details',
+		                                        'qrtz_locks',
+		                                        'qrtz_paused_trigger_grps',
+		                                        'qrtz_scheduler_state',
+		                                        'qrtz_simple_triggers',
+		                                        'qrtz_simprop_triggers',
+		                                        'qrtz_triggers'
+	                                        );";
+                var count = await connection.QueryFirstOrDefaultAsync<int>(check_sql);
+                //初始化 建表
+                if (count == 0)
+                {
+                    string init_sql = await File.ReadAllTextAsync("Tables/tables_postgres.sql");
+                    return await connection.ExecuteAsync(init_sql);
+                }
+            }
+            return 0;
+        }
+
+        public async Task<bool> RemoveErrLogAsync(string jobGroup, string jobName)
+        {
+            try
+            {
+                using (var connection = new NpgsqlConnection(DBProvider.ConnectionString))
+                {
+                    string sql = $@"SELECT
+	                                JOB_DATA
+                                FROM
+	                                QRTZ_JOB_DETAILS
+                                WHERE
+	                                JOB_NAME = @jobName
+                                AND JOB_GROUP = @jobGroup";
+
+                    var byteArray = await connection.ExecuteScalarAsync<byte[]>(sql, new { jobName, jobGroup });
+                    var jsonStr = Encoding.Default.GetString(byteArray);
+                    JObject source = JObject.Parse(jsonStr);
+                    source.Remove("Exception");//移除异常日志 
+                    var modifySql = $@"UPDATE QRTZ_JOB_DETAILS
+                                    SET JOB_DATA = @jobData
+                                    WHERE
+	                                    JOB_NAME = @jobName
+                                    AND JOB_GROUP = @jobGroup";
+                    await connection.ExecuteAsync(modifySql, new { jobName, jobGroup, jobData = Encoding.Default.GetBytes(source.ToString()) });
+                }
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
+        }
+    }
+}

+ 90 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieSQLite.cs

@@ -0,0 +1,90 @@
+using Dapper;
+using Host.Common;
+using Microsoft.Data.Sqlite;
+using Newtonsoft.Json.Linq;
+using Quartz.Impl.AdoJobStore.Common;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public class RepositorieSQLite : IRepositorie
+    {
+        private IDbProvider DBProvider { get; }
+
+        public RepositorieSQLite(IDbProvider dbProvider)
+        {
+            DBProvider = dbProvider;
+        }
+
+        public async Task<int> InitTable()
+        {
+            if (!Directory.Exists("File")) Directory.CreateDirectory("File");
+
+            using (var connection = new SqliteConnection(DBProvider.ConnectionString))
+            {
+                var check_sql = @$"SELECT
+	                                        count(1)
+                                        FROM
+	                                        sqlite_master
+                                        WHERE
+	                                        type = 'table'
+                                        AND name IN (
+	                                        'QRTZ_JOB_DETAILS',
+	                                        'QRTZ_TRIGGERS',
+	                                        'QRTZ_SIMPLE_TRIGGERS',
+	                                        'QRTZ_SIMPROP_TRIGGERS',
+	                                        'QRTZ_CRON_TRIGGERS',
+	                                        'QRTZ_BLOB_TRIGGERS',
+	                                        'QRTZ_CALENDARS',
+	                                        'QRTZ_PAUSED_TRIGGER_GRPS',
+	                                        'QRTZ_FIRED_TRIGGERS',
+	                                        'QRTZ_SCHEDULER_STATE',
+	                                        'QRTZ_LOCKS'
+                                        );";
+                var count = await connection.QueryFirstOrDefaultAsync<int>(check_sql);
+                //初始化 建表
+                if (count == 0)
+                {
+                    string init_sql = await File.ReadAllTextAsync("Tables/tables_sqlite.sql");
+                    return await connection.ExecuteAsync(init_sql);
+                }
+            }
+            return 0;
+        }
+        public async Task<bool> RemoveErrLogAsync(string jobGroup, string jobName)
+        {
+            try
+            {
+                using (var connection = new SqliteConnection(DBProvider.ConnectionString))
+                {
+                    string sql = $@"SELECT
+	                                JOB_DATA
+                                FROM
+	                                QRTZ_JOB_DETAILS
+                                WHERE
+	                                JOB_NAME = @jobName
+                                AND JOB_GROUP = @jobGroup";
+
+                    var byteArray = await connection.ExecuteScalarAsync<byte[]>(sql, new { jobName, jobGroup });
+                    var jsonStr = Encoding.Default.GetString(byteArray);
+                    JObject source = JObject.Parse(jsonStr);
+                    source.Remove("Exception");//移除异常日志 
+                    var modifySql = $@"UPDATE QRTZ_JOB_DETAILS
+                                    SET JOB_DATA = @jobData
+                                    WHERE
+	                                    JOB_NAME = @jobName
+                                    AND JOB_GROUP = @jobGroup";
+                    await connection.ExecuteAsync(modifySql, new { jobName, jobGroup, jobData = source.ToString() });
+                }
+
+                return true;
+            }
+            catch
+            {
+                return false;
+            }
+        }
+    }
+}

+ 87 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Repositories/RepositorieSqlServer.cs

@@ -0,0 +1,87 @@
+using Dapper;
+using Microsoft.Data.SqlClient;
+using Newtonsoft.Json.Linq;
+using Quartz.Impl.AdoJobStore.Common;
+using System;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Host.Repositories
+{
+    public class RepositorieSqlServer : IRepositorie
+    {
+        private IDbProvider DBProvider { get; }
+        public RepositorieSqlServer(IDbProvider dbProvider)
+        {
+            DBProvider = dbProvider;
+        }
+
+        public async Task<int> InitTable()
+        {
+            using (var connection = new SqlConnection(DBProvider.ConnectionString))
+            {
+                var check_sql = @"SELECT
+	                                    COUNT (1)
+                                    FROM
+	                                    sys.tables
+                                    WHERE
+	                                    name IN (
+		                                    'QRTZ_BLOB_TRIGGERS',
+		                                    'QRTZ_CALENDARS',
+		                                    'QRTZ_CRON_TRIGGERS',
+		                                    'QRTZ_FIRED_TRIGGERS',
+		                                    'QRTZ_JOB_DETAILS',
+		                                    'QRTZ_LOCKS',
+		                                    'QRTZ_PAUSED_TRIGGER_GRPS',
+		                                    'QRTZ_SCHEDULER_STATE',
+		                                    'QRTZ_SIMPLE_TRIGGERS',
+		                                    'QRTZ_SIMPROP_TRIGGERS',
+		                                    'QRTZ_TRIGGERS'
+	                                    );";
+                var count = await connection.QueryFirstOrDefaultAsync<int>(check_sql);
+                //初始化 建表
+                if (count == 0)
+                {
+                    string init_sql = await File.ReadAllTextAsync("Tables/tables_sqlServer.sql");
+                    return await connection.ExecuteAsync(init_sql);
+                }
+            }
+            return 0;
+        }
+
+        public async Task<bool> RemoveErrLogAsync(string jobGroup, string jobName)
+        {
+            try
+            {
+                using (var connection = new SqlConnection(DBProvider.ConnectionString))
+                {
+                    string sql = $@"SELECT
+	                                JOB_DATA
+                                FROM
+	                                QRTZ_JOB_DETAILS
+                                WHERE
+	                                JOB_NAME = @jobName
+                                AND JOB_GROUP = @jobGroup";
+
+                    var byteArray = await connection.ExecuteScalarAsync<byte[]>(sql, new { jobName, jobGroup });
+                    var jsonStr = Encoding.Default.GetString(byteArray);
+                    JObject source = JObject.Parse(jsonStr);
+                    source.Remove("Exception");//移除异常日志 
+                    var modifySql = $@"UPDATE QRTZ_JOB_DETAILS
+                                    SET JOB_DATA = @jobData
+                                    WHERE
+	                                    JOB_NAME = @jobName
+                                    AND JOB_GROUP = @jobGroup";
+                    await connection.ExecuteAsync(modifySql, new { jobName, jobGroup, jobData = Encoding.Default.GetBytes(source.ToString()) });
+                }
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
+        }
+    }
+}

+ 25 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/ScheduleManage.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Host
+{
+    public class ScheduleManage
+    {
+        internal ScheduleEntity GetScheduleModel(string jobGroup, string jobName)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal void UpdateScheduleStatus(ScheduleEntity scheduleModel)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal void RemoveScheduleModel(string jobGroup, string jobName)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 35 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Services/HostedService.cs

@@ -0,0 +1,35 @@
+using Host.Managers;
+using Microsoft.Extensions.Hosting;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Host.Services
+{
+    public class HostedService : IHostedService
+    {
+        private SchedulerCenter schedulerCenter;
+        private MqttManager mqttManager;
+        public HostedService(SchedulerCenter schedulerCenter)
+        {
+            this.schedulerCenter = schedulerCenter;
+            mqttManager = MqttManager.Instance;
+        }
+
+        public async Task StartAsync(CancellationToken cancellationToken)
+        {
+            //开启调度器
+            await schedulerCenter.StartScheduleAsync();
+
+            //启动mqtt
+            await mqttManager.RestartAsync();
+
+            //启动Rabbit
+            await RabbitMQManager.Instance.RestartAsync();
+        }
+
+        public Task StopAsync(CancellationToken cancellationToken)
+        {
+            return Task.CompletedTask;
+        }
+    }
+}

+ 180 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Startup.cs

@@ -0,0 +1,180 @@
+using Host.Filters;
+using Host.Managers;
+using Host.Services;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.PlatformAbstractions;
+using Microsoft.OpenApi.Models;
+using Serilog;
+using Serilog.Events;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Host
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            // 日志配置
+            LogConfig();
+
+            #region 跨域     
+            services.AddCors(options =>
+            {
+                options.AddPolicy("AllowSameDomain", policyBuilder =>
+                {
+                    policyBuilder
+                        .AllowAnyMethod()
+                        .AllowAnyHeader();
+
+                    var allowedHosts = Configuration.GetSection("AllowedHosts").Get<List<string>>();
+                    if (allowedHosts?.Any(t => t == "*") ?? false)
+                        policyBuilder.AllowAnyOrigin(); //允许任何来源的主机访问
+                    else if (allowedHosts?.Any() ?? false)
+                        policyBuilder.AllowCredentials().WithOrigins(allowedHosts.ToArray()); //允许类似http://localhost:8080等主机访问
+                });
+            });
+
+            //services.AddRouting(r => r.SuppressCheckForUnhandledSecurityMetadata = true);
+            #endregion
+
+            //services.AddMvc();
+            services.AddControllersWithViews(
+                t =>
+                {
+                    t.Filters.Add<AuthorizationFilter>();
+                }).AddNewtonsoftJson();
+
+            services.AddHostedService<HostedService>();
+            services.AddSingleton<SchedulerCenter>();
+
+            services.AddSwaggerGen(options =>
+            {
+                options.SwaggerDoc("v1", new OpenApiInfo
+                {
+                    Version = "v1",
+                    Title = "MsSystem API"
+                });
+
+                //Determine base path for the application.  
+                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
+                //Set the comments path for the swagger json and ui.  
+                var xmlPath = Path.Combine(basePath, "Host.xml");
+                options.IncludeXmlComments(xmlPath);
+            });
+
+
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+
+            //app.UseMvc();
+
+            app.Use(async (context, next) =>
+            {
+                await next();
+                if (context.Response.StatusCode == 404 &&
+                   !Path.HasExtension(context.Request.Path.Value) &&
+                   !context.Request.Path.Value.StartsWith("/api/"))
+                {
+                    context.Request.Path = "/index.html";
+                    await next();
+                }
+            });
+
+            //app.UseMvcWithDefaultRoute();
+
+            app.UseDefaultFiles();
+            app.UseStaticFiles();
+            app.UseSwagger();
+            app.UseSwaggerUI(c =>
+            {
+                c.SwaggerEndpoint("/swagger/v1/swagger.json", "MsSystem API V1");
+            });
+
+            app.UseRouting();
+            //https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.0
+            app.UseCors("AllowSameDomain");
+            app.UseAuthorization();
+            app.UseEndpoints(endpoints =>
+            {
+                endpoints.MapControllers();
+            });
+        }
+
+        /// <summary>
+        /// 日志配置
+        /// </summary>      
+        private void LogConfig()
+        {
+            //nuget导入
+            //Serilog.Extensions.Logging
+            //Serilog.Sinks.RollingFile
+            //Serilog.Sinks.Async
+            var fileSize = 1024 * 1024 * 10;//10M
+            var fileCount = 2;
+            Log.Logger = new LoggerConfiguration()
+                                 .Enrich.FromLogContext()
+                                 .MinimumLevel.Debug()
+                                 .MinimumLevel.Override("System", LogEventLevel.Information)
+                                 .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-Debug.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+                                     }
+                                 ))
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-Information.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+                                     }
+                                 ))
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-Warning.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+                                     }
+                                 ))
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-Error.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+                                     }
+                                 ))
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-Fatal.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+
+                                     }
+                                 ))
+                                 //所有情况
+                                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => true)).WriteTo.Async(
+                                     a =>
+                                     {
+                                         a.RollingFile("File/logs/log-{Date}-All.txt", fileSizeLimitBytes: fileSize, retainedFileCountLimit: fileCount);
+                                     }
+                                 )
+                                .CreateLogger();
+        }
+    }
+}

+ 174 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_firebird.sql

@@ -0,0 +1,174 @@
+-- this script is for Firebird
+-- Firebird DB script submitted by Leonardo Alves and tweaked by siyu wu
+
+DROP TABLE QRTZ_FIRED_TRIGGERS;
+DROP TABLE QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE QRTZ_SCHEDULER_STATE;
+DROP TABLE QRTZ_LOCKS;
+DROP TABLE QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE QRTZ_CRON_TRIGGERS;
+DROP TABLE QRTZ_BLOB_TRIGGERS;
+DROP TABLE QRTZ_TRIGGERS;
+DROP TABLE QRTZ_JOB_DETAILS;
+DROP TABLE QRTZ_CALENDARS;
+
+
+CREATE TABLE QRTZ_JOB_DETAILS (
+    SCHED_NAME         VARCHAR(120) NOT NULL,
+    JOB_NAME           VARCHAR(150) NOT NULL,
+    JOB_GROUP          VARCHAR(150) NOT NULL,
+    DESCRIPTION        VARCHAR(250) default NULL,
+    JOB_CLASS_NAME     VARCHAR(250) NOT NULL,
+    IS_DURABLE         SMALLINT NOT NULL,
+    IS_NONCONCURRENT   SMALLINT NOT NULL,
+    IS_UPDATE_DATA     SMALLINT NOT NULL,
+    REQUESTS_RECOVERY  SMALLINT NOT NULL,
+    JOB_DATA           BLOB DEFAULT NULL,
+    CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_TRIGGERS (
+    SCHED_NAME      VARCHAR(120) NOT NULL,
+    TRIGGER_NAME    VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP   VARCHAR(150) NOT NULL,
+    JOB_NAME        VARCHAR(150) NOT NULL,
+    JOB_GROUP       VARCHAR(150) NOT NULL,
+    DESCRIPTION     VARCHAR(250) DEFAULT NULL,
+    NEXT_FIRE_TIME  BIGINT DEFAULT NULL,
+    PREV_FIRE_TIME  BIGINT DEFAULT NULL,
+    PRIORITY        INTEGER DEFAULT NULL,
+    TRIGGER_STATE   VARCHAR(16) NOT NULL,
+    TRIGGER_TYPE    VARCHAR(8) NOT NULL,
+    START_TIME      BIGINT NOT NULL,
+    END_TIME        BIGINT DEFAULT NULL,
+    CALENDAR_NAME   VARCHAR(200) DEFAULT NULL,
+    MISFIRE_INSTR   SMALLINT DEFAULT NULL,
+    JOB_DATA        BLOB DEFAULT NULL,
+    CONSTRAINT PK_QRTZ_TRIGGERS PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    CONSTRAINT FK_QRTZ_TRIGGERS_1 FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP)
+    REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME, JOB_NAME, JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+    SCHED_NAME       VARCHAR(120) NOT NULL,
+    TRIGGER_NAME     VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP    VARCHAR(150) NOT NULL,
+    REPEAT_COUNT     BIGINT NOT NULL,
+    REPEAT_INTERVAL  BIGINT NOT NULL,
+    TIMES_TRIGGERED  BIGINT NOT NULL,
+    CONSTRAINT PK_QRTZ_SIMPLE_TRIGGERS PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+    SCHED_NAME       VARCHAR(120) NOT NULL,
+    TRIGGER_NAME     VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP    VARCHAR(150) NOT NULL,
+    CRON_EXPRESSION  VARCHAR(250) NOT NULL,
+    TIME_ZONE_ID     VARCHAR(80),
+    CONSTRAINT PK_QRTZ_CRON_TRIGGERS PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    CONSTRAINT FK_QRTZ_CRON_TRIGGERS_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME, TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS (
+    SCHED_NAME     VARCHAR(120) NOT NULL,
+    TRIGGER_NAME   VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(150) NOT NULL,
+    STR_PROP_1     VARCHAR(512) DEFAULT NULL,
+    STR_PROP_2     VARCHAR(512) DEFAULT NULL,
+    STR_PROP_3     VARCHAR(512) DEFAULT NULL,
+    INT_PROP_1     INTEGER DEFAULT NULL,
+    INT_PROP_2     INTEGER DEFAULT NULL,
+    LONG_PROP_1    BIGINT DEFAULT NULL,
+    LONG_PROP_2    BIGINT DEFAULT NULL,
+    DEC_PROP_1     NUMERIC(9,0) DEFAULT  NULL,
+    DEC_PROP_2     NUMERIC(9,0) DEFAULT NULL,
+    BOOL_PROP_1    SMALLINT DEFAULT NULL,
+    BOOL_PROP_2    SMALLINT DEFAULT NULL,
+    TIME_ZONE_ID   VARCHAR(80) DEFAULT NULL,
+    CONSTRAINT PK_QRTZ_SIMPROP_TRIGGERS PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP),
+    CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME, TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+    SCHED_NAME     VARCHAR(120) NOT NULL,
+    TRIGGER_NAME   VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(150) NOT NULL,
+    BLOB_DATA      BLOB DEFAULT NULL,
+    CONSTRAINT PK_QRTZ_BLOB_TRIGGERS PRIMARY KEY (SCHED_NAME, TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT FK_QRTZ_BLOB_TRIGGERS_1 FOREIGN KEY (SCHED_NAME, TRIGGER_NAME,TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME, TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_CALENDARS (
+    SCHED_NAME     VARCHAR(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR(200) NOT NULL,
+    CALENDAR       BLOB NOT NULL,
+    CONSTRAINT PK_QRTZ_CALENDARS PRIMARY KEY (SCHED_NAME, CALENDAR_NAME)
+);
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+    SCHED_NAME     VARCHAR(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(150) NOT NULL,
+    CONSTRAINT PK_QRTZ_PAUSED_TRIGGER_GRPS PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+    SCHED_NAME         VARCHAR(120) NOT NULL,
+    ENTRY_ID           VARCHAR(140) NOT NULL,
+    TRIGGER_NAME       VARCHAR(150) NOT NULL,
+    TRIGGER_GROUP      VARCHAR(150) NOT NULL,
+    INSTANCE_NAME      VARCHAR(200) NOT NULL,
+    FIRED_TIME         BIGINT NOT NULL,
+    SCHED_TIME         BIGINT NOT NULL,
+    PRIORITY           INTEGER NOT NULL,
+    STATE              VARCHAR(16) NOT NULL,
+    JOB_NAME           VARCHAR(150) DEFAULT NULL,
+    JOB_GROUP          VARCHAR(150) DEFAULT NULL,
+    IS_NONCONCURRENT   SMALLINT NOT NULL,
+    REQUESTS_RECOVERY  SMALLINT DEFAULT NULL,
+    CONSTRAINT PK_QRTZ_FIRED_TRIGGERS PRIMARY KEY (SCHED_NAME, ENTRY_ID)
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+    SCHED_NAME         VARCHAR(120) NOT NULL,
+    INSTANCE_NAME      VARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME  BIGINT NOT NULL,
+    CHECKIN_INTERVAL   BIGINT NOT NULL,
+    CONSTRAINT PK_QRTZ_SCHEDULER_STATE PRIMARY KEY (SCHED_NAME, INSTANCE_NAME)
+);
+
+CREATE TABLE QRTZ_LOCKS (
+    SCHED_NAME  VARCHAR(120) NOT NULL,
+    LOCK_NAME   VARCHAR(40) NOT NULL,
+    CONSTRAINT PK_QRTZ_LOCKS PRIMARY KEY (SCHED_NAME, LOCK_NAME)
+);
+
+CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+
+COMMIT;

+ 179 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_mysql_innodb.sql

@@ -0,0 +1,179 @@
+# By: Ron Cordell - roncordell
+#  I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
+
+
+# make sure you have UTF-8 collaction for best .NET interoperability
+# CREATE DATABASE quartznet CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+
+CREATE TABLE QRTZ_JOB_DETAILS(
+SCHED_NAME VARCHAR(120) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+JOB_CLASS_NAME VARCHAR(250) NOT NULL,
+IS_DURABLE BOOLEAN NOT NULL,
+IS_NONCONCURRENT BOOLEAN NOT NULL,
+IS_UPDATE_DATA BOOLEAN NOT NULL,
+REQUESTS_RECOVERY BOOLEAN NOT NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+NEXT_FIRE_TIME BIGINT(19) NULL,
+PREV_FIRE_TIME BIGINT(19) NULL,
+PRIORITY INTEGER NULL,
+TRIGGER_STATE VARCHAR(16) NOT NULL,
+TRIGGER_TYPE VARCHAR(8) NOT NULL,
+START_TIME BIGINT(19) NOT NULL,
+END_TIME BIGINT(19) NULL,
+CALENDAR_NAME VARCHAR(200) NULL,
+MISFIRE_INSTR SMALLINT(2) NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+REPEAT_COUNT BIGINT(7) NOT NULL,
+REPEAT_INTERVAL BIGINT(12) NOT NULL,
+TIMES_TRIGGERED BIGINT(10) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+CRON_EXPRESSION VARCHAR(120) NOT NULL,
+TIME_ZONE_ID VARCHAR(80),
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 BOOLEAN NULL,
+    BOOL_PROP_2 BOOLEAN NULL,
+    TIME_ZONE_ID VARCHAR(80) NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+BLOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_CALENDARS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+CALENDAR_NAME VARCHAR(200) NOT NULL,
+CALENDAR BLOB NOT NULL,
+PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+ENTRY_ID VARCHAR(140) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+FIRED_TIME BIGINT(19) NOT NULL,
+SCHED_TIME BIGINT(19) NOT NULL,
+PRIORITY INTEGER NOT NULL,
+STATE VARCHAR(16) NOT NULL,
+JOB_NAME VARCHAR(200) NULL,
+JOB_GROUP VARCHAR(200) NULL,
+IS_NONCONCURRENT BOOLEAN NULL,
+REQUESTS_RECOVERY BOOLEAN NULL,
+PRIMARY KEY (SCHED_NAME,ENTRY_ID))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+SCHED_NAME VARCHAR(120) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+LAST_CHECKIN_TIME BIGINT(19) NOT NULL,
+CHECKIN_INTERVAL BIGINT(19) NOT NULL,
+PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_LOCKS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+LOCK_NAME VARCHAR(40) NOT NULL,
+PRIMARY KEY (SCHED_NAME,LOCK_NAME))
+ENGINE=InnoDB;
+
+CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+
+commit; 

+ 194 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_oracle.sql

@@ -0,0 +1,194 @@
+--
+-- A hint submitted by a user: Oracle DB MUST be created as "shared" and the 
+-- job_queue_processes parameter  must be greater than 2
+-- However, these settings are pretty much standard after any
+-- Oracle install, so most users need not worry about this.
+--
+-- Many other users (including the primary author of Quartz) have had success
+-- running in dedicated mode, so only consider the above as a hint ;-)
+--
+
+delete from qrtz_fired_triggers;
+delete from qrtz_simple_triggers;
+delete from qrtz_simprop_triggers;
+delete from qrtz_cron_triggers;
+delete from qrtz_blob_triggers;
+delete from qrtz_triggers;
+delete from qrtz_job_details;
+delete from qrtz_calendars;
+delete from qrtz_paused_trigger_grps;
+delete from qrtz_locks;
+delete from qrtz_scheduler_state;
+
+drop table qrtz_calendars;
+drop table qrtz_fired_triggers;
+drop table qrtz_blob_triggers;
+drop table qrtz_cron_triggers;
+drop table qrtz_simple_triggers;
+drop table qrtz_simprop_triggers;
+drop table qrtz_triggers;
+drop table qrtz_job_details;
+drop table qrtz_paused_trigger_grps;
+drop table qrtz_locks;
+drop table qrtz_scheduler_state;
+
+
+CREATE TABLE qrtz_job_details
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL,
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    JOB_CLASS_NAME   VARCHAR2(250) NOT NULL, 
+    IS_DURABLE VARCHAR2(1) NOT NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
+    IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+CREATE TABLE qrtz_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL, 
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    NEXT_FIRE_TIME NUMBER(19) NULL,
+    PREV_FIRE_TIME NUMBER(19) NULL,
+    PRIORITY NUMBER(13) NULL,
+    TRIGGER_STATE VARCHAR2(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR2(8) NOT NULL,
+    START_TIME NUMBER(19) NOT NULL,
+    END_TIME NUMBER(19) NULL,
+    CALENDAR_NAME VARCHAR2(200) NULL,
+    MISFIRE_INSTR NUMBER(2) NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) 
+      REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) 
+);
+CREATE TABLE qrtz_simple_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    REPEAT_COUNT NUMBER(7) NOT NULL,
+    REPEAT_INTERVAL NUMBER(12) NOT NULL,
+    TIMES_TRIGGERED NUMBER(10) NOT NULL,
+    CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_cron_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR2(120) NOT NULL,
+    TIME_ZONE_ID VARCHAR2(80),
+    CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_simprop_triggers
+  (          
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    STR_PROP_1 VARCHAR2(512) NULL,
+    STR_PROP_2 VARCHAR2(512) NULL,
+    STR_PROP_3 VARCHAR2(512) NULL,
+    INT_PROP_1 NUMBER(10) NULL,
+    INT_PROP_2 NUMBER(10) NULL,
+    LONG_PROP_1 NUMBER(19) NULL,
+    LONG_PROP_2 NUMBER(19) NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR2(1) NULL,
+    BOOL_PROP_2 VARCHAR2(1) NULL,
+    TIME_ZONE_ID VARCHAR2(80) NULL,
+    CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_blob_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_calendars
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR2(200) NOT NULL, 
+    CALENDAR BLOB NOT NULL,
+    CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR2(200) NOT NULL, 
+    CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_fired_triggers 
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    ENTRY_ID VARCHAR2(140) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    FIRED_TIME NUMBER(19) NOT NULL,
+    SCHED_TIME NUMBER(19) NOT NULL,
+	PRIORITY NUMBER(13) NOT NULL,
+    STATE VARCHAR2(16) NOT NULL,
+    JOB_NAME VARCHAR2(200) NULL,
+    JOB_GROUP VARCHAR2(200) NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NULL,
+    CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+CREATE TABLE qrtz_scheduler_state 
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    LAST_CHECKIN_TIME NUMBER(19) NOT NULL,
+    CHECKIN_INTERVAL NUMBER(13) NOT NULL,
+    CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+CREATE TABLE qrtz_locks
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    LOCK_NAME  VARCHAR2(40) NOT NULL, 
+    CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+
+create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
+
+create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
+create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
+create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
+create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
+create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
+
+

+ 169 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_postgres.sql

@@ -0,0 +1,169 @@
+DROP TABLE IF EXISTS qrtz_fired_triggers;
+DROP TABLE IF EXISTS qrtz_paused_trigger_grps;
+DROP TABLE IF EXISTS qrtz_scheduler_state;
+DROP TABLE IF EXISTS qrtz_locks;
+DROP TABLE IF EXISTS qrtz_simprop_triggers;
+DROP TABLE IF EXISTS qrtz_simple_triggers;
+DROP TABLE IF EXISTS qrtz_cron_triggers;
+DROP TABLE IF EXISTS qrtz_blob_triggers;
+DROP TABLE IF EXISTS qrtz_triggers;
+DROP TABLE IF EXISTS qrtz_job_details;
+DROP TABLE IF EXISTS qrtz_calendars;
+
+
+CREATE TABLE qrtz_job_details
+  (
+    sched_name VARCHAR(120) NOT NULL,
+	job_name  VARCHAR(200) NOT NULL,
+    job_group VARCHAR(200) NOT NULL,
+    description VARCHAR(250) NULL,
+    job_class_name   VARCHAR(250) NOT NULL, 
+    is_durable BOOL NOT NULL,
+    is_nonconcurrent BOOL NOT NULL,
+    is_update_data BOOL NOT NULL,
+	requests_recovery BOOL NOT NULL,
+    job_data BYTEA NULL,
+    PRIMARY KEY (sched_name,job_name,job_group)
+);
+
+CREATE TABLE qrtz_triggers
+  (
+    sched_name VARCHAR(120) NOT NULL,
+	trigger_name VARCHAR(150) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL,
+    job_name  VARCHAR(200) NOT NULL, 
+    job_group VARCHAR(200) NOT NULL,
+    description VARCHAR(250) NULL,
+    next_fire_time BIGINT NULL,
+    prev_fire_time BIGINT NULL,
+    priority INTEGER NULL,
+    trigger_state VARCHAR(16) NOT NULL,
+    trigger_type VARCHAR(8) NOT NULL,
+    start_time BIGINT NOT NULL,
+    end_time BIGINT NULL,
+    calendar_name VARCHAR(200) NULL,
+    misfire_instr SMALLINT NULL,
+    job_data BYTEA NULL,
+    PRIMARY KEY (sched_name,trigger_name,trigger_group),
+    FOREIGN KEY (sched_name,job_name,job_group) 
+		REFERENCES qrtz_job_details(sched_name,job_name,job_group) 
+);
+
+CREATE TABLE qrtz_simple_triggers
+  (
+    sched_name VARCHAR(120) NOT NULL,
+	trigger_name VARCHAR(150) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL,
+    repeat_count BIGINT NOT NULL,
+    repeat_interval BIGINT NOT NULL,
+    times_triggered BIGINT NOT NULL,
+    PRIMARY KEY (sched_name,trigger_name,trigger_group),
+    FOREIGN KEY (sched_name,trigger_name,trigger_group) 
+		REFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE
+);
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS 
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    trigger_name VARCHAR (150) NOT NULL ,
+    trigger_group VARCHAR (150) NOT NULL ,
+    str_prop_1 VARCHAR (512) NULL,
+    str_prop_2 VARCHAR (512) NULL,
+    str_prop_3 VARCHAR (512) NULL,
+    int_prop_1 INTEGER NULL,
+    int_prop_2 INTEGER NULL,
+    long_prop_1 BIGINT NULL,
+    long_prop_2 BIGINT NULL,
+    dec_prop_1 NUMERIC NULL,
+    dec_prop_2 NUMERIC NULL,
+    bool_prop_1 BOOL NULL,
+    bool_prop_2 BOOL NULL,
+	time_zone_id VARCHAR(80) NULL,
+	PRIMARY KEY (sched_name,trigger_name,trigger_group),
+    FOREIGN KEY (sched_name,trigger_name,trigger_group) 
+		REFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE
+);
+
+CREATE TABLE qrtz_cron_triggers
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    trigger_name VARCHAR(150) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL,
+    cron_expression VARCHAR(250) NOT NULL,
+    time_zone_id VARCHAR(80),
+    PRIMARY KEY (sched_name,trigger_name,trigger_group),
+    FOREIGN KEY (sched_name,trigger_name,trigger_group) 
+		REFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE
+);
+
+CREATE TABLE qrtz_blob_triggers
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    trigger_name VARCHAR(150) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL,
+    blob_data BYTEA NULL,
+    PRIMARY KEY (sched_name,trigger_name,trigger_group),
+    FOREIGN KEY (sched_name,trigger_name,trigger_group) 
+		REFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE
+);
+
+CREATE TABLE qrtz_calendars
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    calendar_name  VARCHAR(200) NOT NULL, 
+    calendar BYTEA NOT NULL,
+    PRIMARY KEY (sched_name,calendar_name)
+);
+
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL, 
+    PRIMARY KEY (sched_name,trigger_group)
+);
+
+CREATE TABLE qrtz_fired_triggers 
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    entry_id VARCHAR(140) NOT NULL,
+    trigger_name VARCHAR(150) NOT NULL,
+    trigger_group VARCHAR(150) NOT NULL,
+    instance_name VARCHAR(200) NOT NULL,
+    fired_time BIGINT NOT NULL,
+	sched_time BIGINT NOT NULL,
+    priority INTEGER NOT NULL,
+    state VARCHAR(16) NOT NULL,
+    job_name VARCHAR(200) NULL,
+    job_group VARCHAR(200) NULL,
+    is_nonconcurrent BOOL NOT NULL,
+    requests_recovery BOOL NULL,
+    PRIMARY KEY (sched_name,entry_id)
+);
+
+CREATE TABLE qrtz_scheduler_state 
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    instance_name VARCHAR(200) NOT NULL,
+    last_checkin_time BIGINT NOT NULL,
+    checkin_interval BIGINT NOT NULL,
+    PRIMARY KEY (sched_name,instance_name)
+);
+
+CREATE TABLE qrtz_locks
+  (
+    sched_name VARCHAR (120) NOT NULL,
+    lock_name  VARCHAR(40) NOT NULL, 
+    PRIMARY KEY (sched_name,lock_name)
+);
+
+create index idx_qrtz_j_req_recovery on qrtz_job_details(requests_recovery);
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(next_fire_time);
+create index idx_qrtz_t_state on qrtz_triggers(trigger_state);
+create index idx_qrtz_t_nft_st on qrtz_triggers(next_fire_time,trigger_state);
+create index idx_qrtz_ft_trig_name on qrtz_fired_triggers(trigger_name);
+create index idx_qrtz_ft_trig_group on qrtz_fired_triggers(trigger_group);
+create index idx_qrtz_ft_trig_nm_gp on qrtz_fired_triggers(sched_name,trigger_name,trigger_group);
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(instance_name);
+create index idx_qrtz_ft_job_name on qrtz_fired_triggers(job_name);
+create index idx_qrtz_ft_job_group on qrtz_fired_triggers(job_group);
+create index idx_qrtz_ft_job_req_recovery on qrtz_fired_triggers(requests_recovery);

+ 364 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlServer.sql

@@ -0,0 +1,364 @@
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
+;
+
+IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]'))
+ALTER TABLE [dbo].[QRTZ_JOB_LISTENERS] DROP CONSTRAINT [FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]
+
+IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]'))
+ALTER TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] DROP CONSTRAINT [FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]
+
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CALENDARS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
+;
+
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]') AND type in (N'U'))
+DROP TABLE [dbo].[QRTZ_JOB_LISTENERS]
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_LOCKS]
+;
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]') AND type in (N'U'))
+DROP TABLE [dbo].[QRTZ_TRIGGER_LISTENERS]
+
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].QRTZ_SIMPROP_TRIGGERS
+;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_TRIGGERS]
+;
+
+CREATE TABLE [dbo].[QRTZ_CALENDARS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [CALENDAR_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [CALENDAR] [VARBINARY](MAX) NOT NULL
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [CRON_EXPRESSION] [NVARCHAR] (120)  NOT NULL ,
+  [TIME_ZONE_ID] [NVARCHAR] (80) 
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [ENTRY_ID] [NVARCHAR] (140)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [FIRED_TIME] [BIGINT] NOT NULL ,
+  [SCHED_TIME] [BIGINT] NOT NULL ,
+  [PRIORITY] [INTEGER] NOT NULL ,
+  [STATE] [NVARCHAR] (16)  NOT NULL,
+  [JOB_NAME] [NVARCHAR] (150)  NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NULL ,
+  [IS_NONCONCURRENT] BIT  NULL ,
+  [REQUESTS_RECOVERY] BIT  NULL 
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL 
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
+  [CHECKIN_INTERVAL] [BIGINT] NOT NULL
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_LOCKS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [LOCK_NAME] [NVARCHAR] (40)  NOT NULL 
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [DESCRIPTION] [NVARCHAR] (250) NULL ,
+  [JOB_CLASS_NAME] [NVARCHAR] (250)  NOT NULL ,
+  [IS_DURABLE] BIT  NOT NULL ,
+  [IS_NONCONCURRENT] BIT  NOT NULL ,
+  [IS_UPDATE_DATA] BIT  NOT NULL ,
+  [REQUESTS_RECOVERY] BIT  NOT NULL ,
+  [JOB_DATA] [VARBINARY](MAX) NULL
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [REPEAT_COUNT] [INTEGER] NOT NULL ,
+  [REPEAT_INTERVAL] [BIGINT] NOT NULL ,
+  [TIMES_TRIGGERED] [INTEGER] NOT NULL
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [STR_PROP_1] [NVARCHAR] (512) NULL,
+  [STR_PROP_2] [NVARCHAR] (512) NULL,
+  [STR_PROP_3] [NVARCHAR] (512) NULL,
+  [INT_PROP_1] [INT] NULL,
+  [INT_PROP_2] [INT] NULL,
+  [LONG_PROP_1] [BIGINT] NULL,
+  [LONG_PROP_2] [BIGINT] NULL,
+  [DEC_PROP_1] [NUMERIC] (13,4) NULL,
+  [DEC_PROP_2] [NUMERIC] (13,4) NULL,
+  [BOOL_PROP_1] BIT NULL,
+  [BOOL_PROP_2] BIT NULL,
+  [TIME_ZONE_ID] [NVARCHAR] (80) NULL 
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [BLOB_DATA] [VARBINARY](MAX) NULL
+)
+;
+
+CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [DESCRIPTION] [NVARCHAR] (250) NULL ,
+  [NEXT_FIRE_TIME] [BIGINT] NULL ,
+  [PREV_FIRE_TIME] [BIGINT] NULL ,
+  [PRIORITY] [INTEGER] NULL ,
+  [TRIGGER_STATE] [NVARCHAR] (16)  NOT NULL ,
+  [TRIGGER_TYPE] [NVARCHAR] (8)  NOT NULL ,
+  [START_TIME] [BIGINT] NOT NULL ,
+  [END_TIME] [BIGINT] NULL ,
+  [CALENDAR_NAME] [NVARCHAR] (200)  NULL ,
+  [MISFIRE_INSTR] [INTEGER] NULL ,
+  [JOB_DATA] [VARBINARY](MAX) NULL
+)
+;
+
+ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [CALENDAR_NAME]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [ENTRY_ID]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [INSTANCE_NAME]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [LOCK_NAME]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].QRTZ_BLOB_TRIGGERS WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_BLOB_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+;
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+;
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+;
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+	[SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+;
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  )
+;
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME)
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE)
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME)
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY)
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
+;

+ 381 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlServerMOT.sql

@@ -0,0 +1,381 @@
+-- This script is for:
+   -- 64-bit Enterprise, Developer, or Evaluation edition of SQL Server 2014
+   -- SQL Server 2016 RTM (pre-SP1) you need Enterprise, Developer, or Evaluation edition.
+   -- SQL Server 2016 SP1 (or later), any edition. 
+
+USE [master];
+GO
+
+-- NOTE: Modify database, path, filegroup, and file names as required
+ALTER DATABASE [enter_db_name_here] ADD FILEGROUP [MemoryOptimizedData] CONTAINS MEMORY_OPTIMIZED_DATA
+GO
+ALTER DATABASE [enter_db_name_here] ADD FILE ( NAME = N'MemoryOptimizedData', FILENAME = N'[enter_path_here]\MemoryOptimizedData' ) TO FILEGROUP [MemoryOptimizedData]
+GO
+ALTER DATABASE [enter_db_name_here] SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON
+GO
+ALTER DATABASE [enter_db_name_here] SET READ_COMMITTED_SNAPSHOT ON WITH NO_WAIT
+GO
+ALTER DATABASE [enter_db_name_here] SET ALLOW_SNAPSHOT_ISOLATION ON
+GO
+
+USE [enter_db_name_here];
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
+GO
+
+IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]'))
+ALTER TABLE [dbo].[QRTZ_JOB_LISTENERS] DROP CONSTRAINT [FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]
+
+IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]'))
+ALTER TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] DROP CONSTRAINT [FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]
+
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CALENDARS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
+GO
+
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]') AND type in (N'U'))
+DROP TABLE [dbo].[QRTZ_JOB_LISTENERS]
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_LOCKS]
+GO
+IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]') AND type in (N'U'))
+DROP TABLE [dbo].[QRTZ_TRIGGER_LISTENERS]
+
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].QRTZ_SIMPROP_TRIGGERS
+GO
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_TRIGGERS]
+GO
+
+CREATE TABLE [dbo].[QRTZ_CALENDARS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [CALENDAR_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [CALENDAR] [VARBINARY](MAX) NOT NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [CRON_EXPRESSION] [NVARCHAR] (120)  NOT NULL ,
+  [TIME_ZONE_ID] [NVARCHAR] (80)
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [ENTRY_ID] [NVARCHAR] (140)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [FIRED_TIME] [BIGINT] NOT NULL ,
+  [SCHED_TIME] [BIGINT] NOT NULL ,
+  [PRIORITY] [INTEGER] NOT NULL ,
+  [STATE] [NVARCHAR] (16)  NOT NULL,
+  [JOB_NAME] [NVARCHAR] (150)  NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NULL ,
+  [IS_NONCONCURRENT] BIT  NULL ,
+  [REQUESTS_RECOVERY] BIT  NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [INSTANCE_NAME] [NVARCHAR] (200)  NOT NULL ,
+  [LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
+  [CHECKIN_INTERVAL] [BIGINT] NOT NULL
+)
+GO
+
+-- NOTE: Review BUCKET_COUNT and modify as required
+CREATE TABLE [dbo].[QRTZ_LOCKS]
+(
+  [ID] [uniqueidentifier] PRIMARY KEY NONCLUSTERED HASH ( [ID] ) WITH ( BUCKET_COUNT = 1000 ) DEFAULT ( newsequentialid() ) NOT NULL,
+  [SCHED_NAME] [nvarchar] ( 120 ) COLLATE Latin1_General_100_BIN2 NOT NULL,
+  [LOCK_NAME] [nvarchar] ( 40 ) COLLATE Latin1_General_100_BIN2 NOT NULL,
+) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA );
+GO
+
+CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [DESCRIPTION] [NVARCHAR] (250) NULL ,
+  [JOB_CLASS_NAME] [NVARCHAR] (250)  NOT NULL ,
+  [IS_DURABLE] BIT  NOT NULL ,
+  [IS_NONCONCURRENT] BIT  NOT NULL ,
+  [IS_UPDATE_DATA] BIT  NOT NULL ,
+  [REQUESTS_RECOVERY] BIT  NOT NULL ,
+  [JOB_DATA] [VARBINARY](MAX) NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [REPEAT_COUNT] [INTEGER] NOT NULL ,
+  [REPEAT_INTERVAL] [BIGINT] NOT NULL ,
+  [TIMES_TRIGGERED] [INTEGER] NOT NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [STR_PROP_1] [NVARCHAR] (512) NULL,
+  [STR_PROP_2] [NVARCHAR] (512) NULL,
+  [STR_PROP_3] [NVARCHAR] (512) NULL,
+  [INT_PROP_1] [INT] NULL,
+  [INT_PROP_2] [INT] NULL,
+  [LONG_PROP_1] [BIGINT] NULL,
+  [LONG_PROP_2] [BIGINT] NULL,
+  [DEC_PROP_1] [NUMERIC] (13,4) NULL,
+  [DEC_PROP_2] [NUMERIC] (13,4) NULL,
+  [BOOL_PROP_1] BIT NULL,
+  [BOOL_PROP_2] BIT NULL,
+  [TIME_ZONE_ID] [NVARCHAR] (80) NULL 
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [BLOB_DATA] [VARBINARY](MAX) NULL
+)
+GO
+
+CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
+  [SCHED_NAME] [NVARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [TRIGGER_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_NAME] [NVARCHAR] (150)  NOT NULL ,
+  [JOB_GROUP] [NVARCHAR] (150)  NOT NULL ,
+  [DESCRIPTION] [NVARCHAR] (250) NULL ,
+  [NEXT_FIRE_TIME] [BIGINT] NULL ,
+  [PREV_FIRE_TIME] [BIGINT] NULL ,
+  [PRIORITY] [INTEGER] NULL ,
+  [TRIGGER_STATE] [NVARCHAR] (16)  NOT NULL ,
+  [TRIGGER_TYPE] [NVARCHAR] (8)  NOT NULL ,
+  [START_TIME] [BIGINT] NOT NULL ,
+  [END_TIME] [BIGINT] NULL ,
+  [CALENDAR_NAME] [NVARCHAR] (200)  NULL ,
+  [MISFIRE_INSTR] [INTEGER] NULL ,
+  [JOB_DATA] [VARBINARY](MAX) NULL
+)
+GO
+
+ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [CALENDAR_NAME]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [ENTRY_ID]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [INSTANCE_NAME]
+  )
+GO
+
+ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].QRTZ_BLOB_TRIGGERS WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_BLOB_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) 
+GO
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+GO
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+GO
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+	[SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE
+GO
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  )
+GO
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME)
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME)
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE)
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE)
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME)
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY)
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP)
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
+GO

+ 181 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/Tables/tables_sqlite.sql

@@ -0,0 +1,181 @@
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+
+
+CREATE TABLE QRTZ_JOB_DETAILS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	JOB_NAME NVARCHAR(150) NOT NULL,
+    JOB_GROUP NVARCHAR(150) NOT NULL,
+    DESCRIPTION NVARCHAR(250) NULL,
+    JOB_CLASS_NAME   NVARCHAR(250) NOT NULL,
+    IS_DURABLE BIT NOT NULL,
+    IS_NONCONCURRENT BIT NOT NULL,
+    IS_UPDATE_DATA BIT  NOT NULL,
+	REQUESTS_RECOVERY BIT NOT NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_TRIGGERS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	TRIGGER_NAME NVARCHAR(150) NOT NULL,
+    TRIGGER_GROUP NVARCHAR(150) NOT NULL,
+    JOB_NAME NVARCHAR(150) NOT NULL,
+    JOB_GROUP NVARCHAR(150) NOT NULL,
+    DESCRIPTION NVARCHAR(250) NULL,
+    NEXT_FIRE_TIME BIGINT NULL,
+    PREV_FIRE_TIME BIGINT NULL,
+    PRIORITY INTEGER NULL,
+    TRIGGER_STATE NVARCHAR(16) NOT NULL,
+    TRIGGER_TYPE NVARCHAR(8) NOT NULL,
+    START_TIME BIGINT NOT NULL,
+    END_TIME BIGINT NULL,
+    CALENDAR_NAME NVARCHAR(200) NULL,
+    MISFIRE_INSTR INTEGER NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	TRIGGER_NAME NVARCHAR(150) NOT NULL,
+    TRIGGER_GROUP NVARCHAR(150) NOT NULL,
+    REPEAT_COUNT BIGINT NOT NULL,
+    REPEAT_INTERVAL BIGINT NOT NULL,
+    TIMES_TRIGGERED BIGINT NOT NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ON DELETE CASCADE
+);
+
+CREATE TRIGGER DELETE_SIMPLE_TRIGGER DELETE ON QRTZ_TRIGGERS
+BEGIN
+	DELETE FROM QRTZ_SIMPLE_TRIGGERS WHERE SCHED_NAME=OLD.SCHED_NAME AND TRIGGER_NAME=OLD.TRIGGER_NAME AND TRIGGER_GROUP=OLD.TRIGGER_GROUP;
+END
+;
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS 
+  (
+    SCHED_NAME NVARCHAR (120) NOT NULL ,
+    TRIGGER_NAME NVARCHAR (150) NOT NULL ,
+    TRIGGER_GROUP NVARCHAR (150) NOT NULL ,
+    STR_PROP_1 NVARCHAR (512) NULL,
+    STR_PROP_2 NVARCHAR (512) NULL,
+    STR_PROP_3 NVARCHAR (512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC NULL,
+    DEC_PROP_2 NUMERIC NULL,
+    BOOL_PROP_1 BIT NULL,
+    BOOL_PROP_2 BIT NULL,
+    TIME_ZONE_ID NVARCHAR(80) NULL,
+	PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+	FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ON DELETE CASCADE
+);
+
+CREATE TRIGGER DELETE_SIMPROP_TRIGGER DELETE ON QRTZ_TRIGGERS
+BEGIN
+	DELETE FROM QRTZ_SIMPROP_TRIGGERS WHERE SCHED_NAME=OLD.SCHED_NAME AND TRIGGER_NAME=OLD.TRIGGER_NAME AND TRIGGER_GROUP=OLD.TRIGGER_GROUP;
+END
+;
+
+CREATE TABLE QRTZ_CRON_TRIGGERS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	TRIGGER_NAME NVARCHAR(150) NOT NULL,
+    TRIGGER_GROUP NVARCHAR(150) NOT NULL,
+    CRON_EXPRESSION NVARCHAR(250) NOT NULL,
+    TIME_ZONE_ID NVARCHAR(80),
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ON DELETE CASCADE
+);
+
+CREATE TRIGGER DELETE_CRON_TRIGGER DELETE ON QRTZ_TRIGGERS
+BEGIN
+	DELETE FROM QRTZ_CRON_TRIGGERS WHERE SCHED_NAME=OLD.SCHED_NAME AND TRIGGER_NAME=OLD.TRIGGER_NAME AND TRIGGER_GROUP=OLD.TRIGGER_GROUP;
+END
+;
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	TRIGGER_NAME NVARCHAR(150) NOT NULL,
+    TRIGGER_GROUP NVARCHAR(150) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ON DELETE CASCADE
+);
+
+CREATE TRIGGER DELETE_BLOB_TRIGGER DELETE ON QRTZ_TRIGGERS
+BEGIN
+	DELETE FROM QRTZ_BLOB_TRIGGERS WHERE SCHED_NAME=OLD.SCHED_NAME AND TRIGGER_NAME=OLD.TRIGGER_NAME AND TRIGGER_GROUP=OLD.TRIGGER_GROUP;
+END
+;
+
+CREATE TABLE QRTZ_CALENDARS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	CALENDAR_NAME  NVARCHAR(200) NOT NULL,
+    CALENDAR BLOB NOT NULL,
+    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	TRIGGER_GROUP NVARCHAR(150) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	ENTRY_ID NVARCHAR(140) NOT NULL,
+    TRIGGER_NAME NVARCHAR(150) NOT NULL,
+    TRIGGER_GROUP NVARCHAR(150) NOT NULL,
+    INSTANCE_NAME NVARCHAR(200) NOT NULL,
+    FIRED_TIME BIGINT NOT NULL,
+    SCHED_TIME BIGINT NOT NULL,
+	PRIORITY INTEGER NOT NULL,
+    STATE NVARCHAR(16) NOT NULL,
+    JOB_NAME NVARCHAR(150) NULL,
+    JOB_GROUP NVARCHAR(150) NULL,
+    IS_NONCONCURRENT BIT NULL,
+    REQUESTS_RECOVERY BIT NULL,
+    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	INSTANCE_NAME NVARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT NOT NULL,
+    CHECKIN_INTERVAL BIGINT NOT NULL,
+    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+
+CREATE TABLE QRTZ_LOCKS
+  (
+    SCHED_NAME NVARCHAR(120) NOT NULL,
+	LOCK_NAME  NVARCHAR(40) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);

+ 10 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/appsettings.Development.json

@@ -0,0 +1,10 @@
+{
+  "Logging": {
+    "IncludeScopes": false,
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}

+ 43 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/appsettings.json

@@ -0,0 +1,43 @@
+{
+  //可跨域地址集合
+  "AllowedHosts": [ "*" ],
+  "Quartz": {
+    "dbProviderName": "SqlServer",
+    "connectionString": "Server=123.60.180.165;Database=dopbiz;uid=sa;pwd=5h3n9)uN;Trusted_Connection=false;TrustServerCertificate=True"
+  },
+  "Logging": {
+    "IncludeScopes": false,
+    "Debug": {
+      "LogLevel": {
+        "Default": "Warning"
+      }
+    },
+    "Console": {
+      "LogLevel": {
+        "Default": "Warning"
+      }
+    }
+  }
+}
+
+//数据源配置
+//"dbProviderName":"OracleODPManaged",
+//"connectionString": "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=xe)));User Id=system;Password=oracle;"
+// # SqlServer 测试通过
+//"dbProviderName":"SqlServer",
+//"connectionString": "Server=localhost;Database=quartznet;User Id=SqlServerUser;Password=SqlServerPassword;"
+//"dbProviderName":"SQLServerMOT",
+//"connectionString": "Server=localhost,1444;Database=quartznet;User Id={SqlServerUser};Password={SqlServerPassword};"
+// # MySql 测试通过
+//"dbProviderName":"MySql",
+//"connectionString": "Server = localhost; Database = quartznet; Uid = quartznet; Pwd = quartznet"
+// # Npgsql 测试通过
+//"dbProviderName":"Npgsql",
+//"connectionString": "Server=127.0.0.1;Port=5432;Userid=quartznet;Password=quartznet;Pooling=true;MinPoolSize=1;MaxPoolSize=20;Timeout=15;SslMode=Disable;Database=quartznet"
+//"dbProviderName":"SQLite",
+//"connectionString": "Data Source=test.db;Version=3;"
+// # SQLite-Microsoft 测试通过
+//"dbProviderName":"SQLite-Microsoft",
+//"connectionString": "Data Source=test.db;"
+//"dbProviderName":"Firebird",
+//"connectionString": "User=SYSDBA;Password=masterkey;Database=/firebird/data/quartz.fdb;DataSource=localhost;Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;"

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/1-es2015.f3b9d43ee6db9fa820da.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/1-es5.f3b9d43ee6db9fa820da.js


+ 529 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/3rdpartylicenses.txt

@@ -0,0 +1,529 @@
+@angular-devkit/build-angular
+MIT
+The MIT License
+
+Copyright (c) 2017 Google, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+@angular/animations
+MIT
+
+@angular/cdk
+MIT
+The MIT License
+
+Copyright (c) 2019 Google LLC.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+@angular/cdk/scrolling
+
+@angular/common
+MIT
+
+@angular/core
+MIT
+
+@angular/forms
+MIT
+
+@angular/platform-browser
+MIT
+
+@angular/router
+MIT
+
+@ant-design/colors
+MIT
+MIT LICENSE
+
+Copyright (c) 2018-present Ant UED, https://xtech.antfin.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+@ant-design/icons-angular
+MIT
+
+@ngx-translate/core
+MIT
+
+@ngx-translate/http-loader
+MIT
+
+core-js
+MIT
+Copyright (c) 2014-2018 Denis Pushkarev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+date-fns
+MIT
+# License
+
+date-fns is licensed under the [MIT license](http://kossnocorp.mit-license.org).
+Read more about MIT at [TLDRLegal](https://tldrlegal.com/license/mit-license).
+
+
+ng-zorro-antd
+MIT
+
+ng-zorro-antd/breadcrumb
+
+ng-zorro-antd/button
+
+ng-zorro-antd/calendar
+
+ng-zorro-antd/checkbox
+
+ng-zorro-antd/collapse
+
+ng-zorro-antd/date-picker
+
+ng-zorro-antd/drawer
+
+ng-zorro-antd/dropdown
+
+ng-zorro-antd/empty
+
+ng-zorro-antd/form
+
+ng-zorro-antd/input
+
+ng-zorro-antd/layout
+
+ng-zorro-antd/message
+
+ng-zorro-antd/modal
+
+ng-zorro-antd/notification
+
+ng-zorro-antd/pagination
+
+ng-zorro-antd/popconfirm
+
+ng-zorro-antd/popover
+
+ng-zorro-antd/radio
+
+ng-zorro-antd/select
+
+ng-zorro-antd/spin
+
+ng-zorro-antd/table
+
+ng-zorro-antd/tabs
+
+undefined
+
+ng-zorro-antd/tag
+
+ng-zorro-antd/time-picker
+
+ng-zorro-antd/tooltip
+
+regenerator-runtime
+MIT
+MIT License
+
+Copyright (c) 2014-present, Facebook, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+rxjs
+Apache-2.0
+                               Apache License
+                         Version 2.0, January 2004
+                      http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+    "License" shall mean the terms and conditions for use, reproduction,
+    and distribution as defined by Sections 1 through 9 of this document.
+
+    "Licensor" shall mean the copyright owner or entity authorized by
+    the copyright owner that is granting the License.
+
+    "Legal Entity" shall mean the union of the acting entity and all
+    other entities that control, are controlled by, or are under common
+    control with that entity. For the purposes of this definition,
+    "control" means (i) the power, direct or indirect, to cause the
+    direction or management of such entity, whether by contract or
+    otherwise, or (ii) ownership of fifty percent (50%) or more of the
+    outstanding shares, or (iii) beneficial ownership of such entity.
+
+    "You" (or "Your") shall mean an individual or Legal Entity
+    exercising permissions granted by this License.
+
+    "Source" form shall mean the preferred form for making modifications,
+    including but not limited to software source code, documentation
+    source, and configuration files.
+
+    "Object" form shall mean any form resulting from mechanical
+    transformation or translation of a Source form, including but
+    not limited to compiled object code, generated documentation,
+    and conversions to other media types.
+
+    "Work" shall mean the work of authorship, whether in Source or
+    Object form, made available under the License, as indicated by a
+    copyright notice that is included in or attached to the work
+    (an example is provided in the Appendix below).
+
+    "Derivative Works" shall mean any work, whether in Source or Object
+    form, that is based on (or derived from) the Work and for which the
+    editorial revisions, annotations, elaborations, or other modifications
+    represent, as a whole, an original work of authorship. For the purposes
+    of this License, Derivative Works shall not include works that remain
+    separable from, or merely link (or bind by name) to the interfaces of,
+    the Work and Derivative Works thereof.
+
+    "Contribution" shall mean any work of authorship, including
+    the original version of the Work and any modifications or additions
+    to that Work or Derivative Works thereof, that is intentionally
+    submitted to Licensor for inclusion in the Work by the copyright owner
+    or by an individual or Legal Entity authorized to submit on behalf of
+    the copyright owner. For the purposes of this definition, "submitted"
+    means any form of electronic, verbal, or written communication sent
+    to the Licensor or its representatives, including but not limited to
+    communication on electronic mailing lists, source code control systems,
+    and issue tracking systems that are managed by, or on behalf of, the
+    Licensor for the purpose of discussing and improving the Work, but
+    excluding communication that is conspicuously marked or otherwise
+    designated in writing by the copyright owner as "Not a Contribution."
+
+    "Contributor" shall mean Licensor and any individual or Legal Entity
+    on behalf of whom a Contribution has been received by Licensor and
+    subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+    this License, each Contributor hereby grants to You a perpetual,
+    worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+    copyright license to reproduce, prepare Derivative Works of,
+    publicly display, publicly perform, sublicense, and distribute the
+    Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+    this License, each Contributor hereby grants to You a perpetual,
+    worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+    (except as stated in this section) patent license to make, have made,
+    use, offer to sell, sell, import, and otherwise transfer the Work,
+    where such license applies only to those patent claims licensable
+    by such Contributor that are necessarily infringed by their
+    Contribution(s) alone or by combination of their Contribution(s)
+    with the Work to which such Contribution(s) was submitted. If You
+    institute patent litigation against any entity (including a
+    cross-claim or counterclaim in a lawsuit) alleging that the Work
+    or a Contribution incorporated within the Work constitutes direct
+    or contributory patent infringement, then any patent licenses
+    granted to You under this License for that Work shall terminate
+    as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+    Work or Derivative Works thereof in any medium, with or without
+    modifications, and in Source or Object form, provided that You
+    meet the following conditions:
+
+    (a) You must give any other recipients of the Work or
+        Derivative Works a copy of this License; and
+
+    (b) You must cause any modified files to carry prominent notices
+        stating that You changed the files; and
+
+    (c) You must retain, in the Source form of any Derivative Works
+        that You distribute, all copyright, patent, trademark, and
+        attribution notices from the Source form of the Work,
+        excluding those notices that do not pertain to any part of
+        the Derivative Works; and
+
+    (d) If the Work includes a "NOTICE" text file as part of its
+        distribution, then any Derivative Works that You distribute must
+        include a readable copy of the attribution notices contained
+        within such NOTICE file, excluding those notices that do not
+        pertain to any part of the Derivative Works, in at least one
+        of the following places: within a NOTICE text file distributed
+        as part of the Derivative Works; within the Source form or
+        documentation, if provided along with the Derivative Works; or,
+        within a display generated by the Derivative Works, if and
+        wherever such third-party notices normally appear. The contents
+        of the NOTICE file are for informational purposes only and
+        do not modify the License. You may add Your own attribution
+        notices within Derivative Works that You distribute, alongside
+        or as an addendum to the NOTICE text from the Work, provided
+        that such additional attribution notices cannot be construed
+        as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and
+    may provide additional or different license terms and conditions
+    for use, reproduction, or distribution of Your modifications, or
+    for any such Derivative Works as a whole, provided Your use,
+    reproduction, and distribution of the Work otherwise complies with
+    the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+    any Contribution intentionally submitted for inclusion in the Work
+    by You to the Licensor shall be under the terms and conditions of
+    this License, without any additional terms or conditions.
+    Notwithstanding the above, nothing herein shall supersede or modify
+    the terms of any separate license agreement you may have executed
+    with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+    names, trademarks, service marks, or product names of the Licensor,
+    except as required for reasonable and customary use in describing the
+    origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+    agreed to in writing, Licensor provides the Work (and each
+    Contributor provides its Contributions) on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+    implied, including, without limitation, any warranties or conditions
+    of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+    PARTICULAR PURPOSE. You are solely responsible for determining the
+    appropriateness of using or redistributing the Work and assume any
+    risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+    whether in tort (including negligence), contract, or otherwise,
+    unless required by applicable law (such as deliberate and grossly
+    negligent acts) or agreed to in writing, shall any Contributor be
+    liable to You for damages, including any direct, indirect, special,
+    incidental, or consequential damages of any character arising as a
+    result of this License or out of the use or inability to use the
+    Work (including but not limited to damages for loss of goodwill,
+    work stoppage, computer failure or malfunction, or any and all
+    other commercial damages or losses), even if such Contributor
+    has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+    the Work or Derivative Works thereof, You may choose to offer,
+    and charge a fee for, acceptance of support, warranty, indemnity,
+    or other liability obligations and/or rights consistent with this
+    License. However, in accepting such obligations, You may act only
+    on Your own behalf and on Your sole responsibility, not on behalf
+    of any other Contributor, and only if You agree to indemnify,
+    defend, and hold each Contributor harmless for any liability
+    incurred by, or claims asserted against, such Contributor by reason
+    of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+    To apply the Apache License to your work, attach the following
+    boilerplate notice, with the fields enclosed by brackets "[]"
+    replaced with your own identifying information. (Don't include
+    the brackets!)  The text should be enclosed in the appropriate
+    comment syntax for the file format. We also recommend that a
+    file or class name and description of purpose be included on the
+    same "printed page" as the copyright notice for easier
+    identification within third-party archives.
+
+ Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ 
+
+
+tinycolor2
+MIT
+Copyright (c), Brian Grinstead, http://briangrinstead.com
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+tslib
+Apache-2.0
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ 
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+
+zone.js
+MIT
+The MIT License
+
+Copyright (c) 2016-2018 Google, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/6-es2015.a4e363a7248c7daffe8a.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/6-es5.a4e363a7248c7daffe8a.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/7-es2015.bfb7deef134855a4f9fd.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/7-es5.bfb7deef134855a4f9fd.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/8-es2015.a1b00527ed656e5e5a76.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/8-es5.a1b00527ed656e5e5a76.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/9-es2015.8365ef5288043f903909.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/9-es5.8365ef5288043f903909.js


+ 118 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/assets/i18n/en.json

@@ -0,0 +1,118 @@
+{
+    "logTitle": "Task scheduling platform",
+    "login": {
+        "任务调度平台": "Task scheduling platform",
+        "请输入登录口令": "Please enter your login password",
+        "提交": "Submit"
+    },
+    "task.list": {
+        "table.th": {
+            "任务名称": "Task Name",
+            "状态": "State",
+            "请求方式": "Request way",
+            "Url": "Address",
+            "异常信息": "Exception Info",
+            "开始时间": "Start Time",
+            "上次执行时间": "Last execution time",
+            "下次执行时间": "Next execution time",
+            "执行计划": "Execution",
+            "描述": "Description",
+            "请求次数": "Triggered",
+            "任务类型": "Task type",
+            "button": {
+                "新增任务": "Add Task",
+                "恢复": "Restore",
+                "复制": "Copy",
+                "删除": "Delete",
+                "编辑": "Editor",
+                "暂停": "Pause",
+                "执行": "Execute",
+                "日志": "Log",
+                "更多": "More"
+            },
+            "tag": {
+                "查看": "View",
+                "正常": "Normal",
+                "暂停": "Paused",
+                "完成": "Complete",
+                "异常": "Error",
+                "阻塞": "Blocked",
+                "不存在": "None",
+                "未知": "Unknown"
+            },
+            "jobType": {
+                "1": "Url",
+                "2": "Emial",
+                "3": "Mqtt",
+                "4": "RabbitMQ",
+                "5": "Hotreload"
+            }
+        },
+        "modal.label": {
+            "任务组名": "Group name",
+            "任务名称": "Task name",
+            "请求地址": "Request URL",
+            "开始时间": "Start time",
+            "结束时间": "End time",
+            "触发器类型": "Trigger type",
+            "Cron表达式": "Cron",
+            "间隔时间": "Interval time",
+            "请求类型": "Request type",
+            "请求头": "Request header",
+            "请求参数": "Request parameter",
+            "任务描述": "Task description",
+            "邮件通知": "Email notification",
+            "参考": "Consult",
+            "不通知": "Not notify",
+            "通知异常": "Notify exception",
+            "通知所有": "Notify all",
+            "任务类型": "Task type",
+            "邮件内容": "Mail content",
+            "收件邮箱": "MailTo",
+            "邮件标题": "Mail title",
+            "邮件": "Email",
+            "热加载": "Hot reload",
+            "秒": "second",
+            "时": "hour",
+            "分": "minute",
+            "天": "day",
+            "主题": "Topic",
+            "消息": "Payload",
+            "队列名称": "Queue",
+            "主体内容": "Body"
+        },
+        "任务列表": "Task list"
+    },
+    "system.setup": {
+        "注销": "logout",
+        "breadcrumb": "system setup",
+        "tabset.tab": {
+            "邮箱设置": "Mailbox settings",
+            "MQTT配置": "MQTT settings",
+            "刷新设置": "Refresh settings",
+            "登录设置": "Login settings",
+            "RabbitMQ配置": "RabbitMQ settings"
+        },
+        "label": {
+            "页面定时刷新时间": "Page refresh time",
+            "发件服务器": "MailHost",
+            "发件邮箱": "MailFrom",
+            "邮箱密码": "MailPassword",
+            "收件邮箱": "MailTo",
+            "秒": "second",
+            "旧登录口令": "Old login password",
+            "新登录口令": "New login password",
+            "主机地址": "Host",
+            "端口": "Port",
+            "客户端ID": "Clinet ID",
+            "用户名": "UserName",
+            "密码": "Password",
+            "连接方式": "Connection method"
+        },
+        "button": {
+            "确定": "Ok",
+            "测试": "Test",
+            "连接测试": "Test connect"
+        }
+    }
+}

+ 118 - 0
MicroServices/QuartzUI/QuartzNetAPI/Host/wwwroot - 副本/assets/i18n/zh.json

@@ -0,0 +1,118 @@
+{
+    "logTitle": "任务调度平台",
+    "login":{
+        "任务调度平台":"任务调度平台",
+        "请输入登录口令":"请输入登录口令",
+        "提交":"提交"
+    },
+    "task.list": {
+        "table.th": {
+            "任务名称": "任务名称",
+            "状态": "状态",
+            "请求方式": "请求方式",
+            "Url": "触发地址",
+            "异常信息": "异常信息",
+            "开始时间": "开始时间",
+            "上次执行时间": "上次执行时间",
+            "下次执行时间": "下次执行时间",
+            "执行计划": "执行计划",
+            "描述": "描述",
+            "请求次数":"触发次数",
+            "任务类型":"任务类型",
+            "button": {
+                "新增任务": "新增任务",
+                "恢复": "恢复",
+                "复制": "复制",
+                "删除": "删除",
+                "编辑": "编辑",
+                "暂停": "暂停",
+                "执行": "执行",
+                "日志": "日志",
+                "更多": "更多"
+            },
+            "tag": {
+                "查看": "查看",
+                "正常": "正常",
+                "暂停": "暂停",
+                "完成": "完成",
+                "异常": "异常",
+                "阻塞": "执行中",
+                "不存在": "不存在",
+                "未知": "未知"
+            },
+            "jobType": {
+                "1": "Url",
+                "2": "邮件",
+                "3": "Mqtt",
+                "4": "RabbitMQ",
+                "5": "热加载"
+            }
+        },
+        "modal.label": {
+            "任务组名": "任务组名",
+            "任务名称": "任务名称",
+            "请求地址": "请求地址",
+            "开始时间": "开始时间",
+            "结束时间": "结束时间",
+            "触发器类型": "触发器类型",
+            "Cron表达式": "Cron表达式",
+            "间隔时间": "间隔时间",
+            "请求类型": "请求类型",
+            "请求头": "请求头",
+            "请求参数": "请求参数",
+            "任务描述": "任务描述",
+            "邮件通知": "邮件通知",
+            "任务类型":"任务类型",
+            "邮件":"邮件",
+            "热加载":"热加载",
+            "邮件内容": "邮件内容",
+            "收件邮箱": "收件邮箱",
+            "邮件标题": "邮件标题",
+            "参考": "参考",
+            "不通知": "不通知",
+            "通知异常": "通知异常",
+            "通知所有": "通知所有",
+            "秒": "秒",
+            "时": "时",
+            "分": "分",
+            "天": "天",
+            "主题":"主题",
+            "消息":"消息",
+            "队列名称":"队列名称",
+            "主体内容":"主体内容"
+        },
+        "任务列表": "任务列表"
+    },
+    "system.setup": {
+        "注销":"注销",
+        "breadcrumb": "系统设置",
+        "tabset.tab": {
+            "邮箱设置": "邮箱配置",
+            "MQTT配置": "MQTT配置",
+            "刷新设置": "刷新设置",
+            "登录设置": "登录设置",
+            "RabbitMQ配置":"RabbitMQ配置"
+        },
+        "label": {
+            "页面定时刷新时间": "页面定时刷新时间",
+            "发件服务器": "发件服务器",
+            "发件邮箱": "发件邮箱",
+            "邮箱密码": "邮箱密码",
+            "收件邮箱": "收件邮箱",
+            "秒": "秒",
+            "旧登录口令": "旧登录口令",
+            "新登录口令": "新登录口令",
+            "主机地址":"主机地址",
+            "端口":"端口",
+            "客户端ID":"客户端ID",
+            "用户名":"用户名",
+            "密码":"密码",
+            "连接方式":"连接方式"
+        },
+        "button": {
+            "确定": "确定",
+            "测试": "测试",
+            "连接测试":"连接测试"
+        }
+    }
+}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio