Startup.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. using System.Diagnostics;
  2. using Admin.NET.Plugin.AiDOP.ChatBI;
  3. using Admin.NET.Plugin.AiDOP.Entity;
  4. using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing;
  5. using Admin.NET.Plugin.AiDOP.Entity.S0.Quality;
  6. using Admin.NET.Plugin.AiDOP.Entity.S0.Sales;
  7. using Admin.NET.Plugin.AiDOP.Entity.S0.Supply;
  8. using Admin.NET.Plugin.AiDOP.Entity.S8;
  9. using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
  10. using Admin.NET.Plugin.AiDOP.Order;
  11. using Admin.NET.Plugin.AiDOP.DataPlatform.Executors;
  12. using Admin.NET.Plugin.AiDOP.DataPlatform.HotWatch;
  13. using Admin.NET.Plugin.AiDOP.Entity.DataPlatform;
  14. using Admin.NET.Plugin.AiDOP.Infrastructure;
  15. using Admin.NET.Plugin.AiDOP.MaterialWarehouse;
  16. using Admin.NET.Plugin.AiDOP.WorkOrder;
  17. using Microsoft.AspNetCore.Builder;
  18. using Microsoft.AspNetCore.Hosting;
  19. using Microsoft.AspNetCore.Mvc;
  20. using Microsoft.Extensions.DependencyInjection;
  21. using Microsoft.Extensions.Hosting;
  22. using SqlSugar;
  23. namespace Admin.NET.Plugin.AiDOP;
  24. /// <summary>
  25. /// AiDOP 插件启动配置(按需扩展 DI)
  26. /// </summary>
  27. [AppStartup(900)]
  28. public class Startup : AppStartup
  29. {
  30. public void ConfigureServices(IServiceCollection services)
  31. {
  32. services.AddHttpClient();
  33. services.AddHttpClient("AidopChatBI.DeepSeek");
  34. services.AddScoped<DeepSeekChatClient>();
  35. services.AddScoped<ChatBIService>();
  36. services.AddConfigurableOptions<S8ActiveFlowWatchOptions>();
  37. services.AddConfigurableOptions<S8MasterDataOptions>();
  38. services.AddConfigurableOptions<AidopPickBillOptions>();
  39. services.AddConfigurableOptions<AidopStockOptions>();
  40. services.AddConfigurableOptions<AidopInventoryOptions>();
  41. services.AddTransient<IInventoryBalanceReader, InventoryBalanceReader>();
  42. services.AddTransient<IInventoryTransactionReader, StdInventoryTransactionReader>();
  43. // WP9:IPickBillCreator 唯一实现为 Facade(避免 Local/Mes 多实现竞注)
  44. services.AddTransient<IPickBillCreator, PickBillCreatorFacade>();
  45. services.AddScoped<AdoS0ExceptionFilter>();
  46. services.AddScoped<AdoS0ResultFilter>();
  47. services.AddScoped<AdoS0ReferenceChecker>();
  48. services.Configure<MvcOptions>(options =>
  49. {
  50. options.Filters.AddService<AdoS0ExceptionFilter>();
  51. options.Filters.AddService<AdoS0ResultFilter>();
  52. });
  53. // MDP 出站事件驱动:入队 Pulse → 立即推送;Period Job 仅兜底
  54. services.AddHostedService<MdpOutboxPushWorker>();
  55. services.AddHostedService<MdpHotWatchWorker>();
  56. services.AddHostedService<Admin.NET.Plugin.AiDOP.DataPlatform.S1Refresh.S1DashboardRebuildWorker>();
  57. services.AddHostedService<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.ModuleRebuildWorker>();
  58. services.AddSingleton<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildCapability, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.ModuleRebuildCapability>();
  59. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildJobStore, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.ModuleRebuildJobStore>();
  60. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildLock, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.ModuleRebuildLock>();
  61. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S1ModuleRebuildHandler>();
  62. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S2ModuleRebuildHandler>();
  63. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S3ModuleRebuildHandler>();
  64. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S4ModuleRebuildHandler>();
  65. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S5ModuleRebuildHandler>();
  66. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S6ModuleRebuildHandler>();
  67. services.AddTransient<Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.IModuleRebuildHandler, Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild.S7ModuleRebuildHandler>();
  68. // S8-DATASET-FOUNDATION-HARDENING-2:S8 取数底座的接口映射显式注册
  69. // (与上方 IModuleRebuildLock 同一先例:本项目不依赖 ITransient 自动按接口注册)。
  70. services.AddTransient<Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.IS8DatasetCatalog, Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.S8DatasetCatalog>();
  71. // S8-STANDARD-DATASET-HARD-CUTOVER-1:IS8LegacySqlDataProvider 及其实现已物理删除。
  72. // S8-RULE01-PURCHASE-DELIVERY-A:接入第一个真实业务数据集 PURCHASE_DELIVERY。
  73. // Catalog 有定义 + Registry 有实现,Enable Gate 才判 READY:
  74. // 缺定义 → 规则连保存都过不了(dataset_not_defined);
  75. // 缺实现 → 可存草稿但不可启用(dataset_provider_not_registered)。
  76. // 两个接口都必须显式注册(同上,不依赖 ITransient 自动按接口注册)。
  77. services.AddTransient<Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.IS8DatasetDefinitionSource, Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers.S8BusinessDatasetDefinitions>();
  78. services.AddTransient<Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.IS8MonitoringDataProvider, Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers.S8PurchaseDeliveryDataProvider>();
  79. }
  80. /// <summary>
  81. /// 开发环境下为 Demo 表执行 CodeFirst(表已存在则跳过变更,行为取决于 SqlSugar 配置)。
  82. /// </summary>
  83. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  84. {
  85. try
  86. {
  87. AidopMenuLinkSync.EnsureLinked(app.ApplicationServices);
  88. }
  89. catch (Exception ex)
  90. {
  91. Trace.TraceWarning("Ai-DOP AidopMenuLinkSync: " + ex);
  92. }
  93. try
  94. {
  95. using var scopeS4 = app.ApplicationServices.CreateScope();
  96. var dbS4 = scopeS4.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  97. dbS4.CodeFirst.InitTables(
  98. typeof(AdoSmartOpsLayoutItem),
  99. typeof(AdoSmartOpsHomeModule),
  100. typeof(AdoSmartOpsKpiMaster),
  101. typeof(AdoSmartOpsDashboardPageConfig),
  102. typeof(AdoSmartOpsDashboardWidget),
  103. typeof(AdoSmartOpsImprovementPlan),
  104. typeof(AdoMdpHotWatch),
  105. typeof(Admin.NET.Plugin.AiDOP.Entity.SmartOps.AdoS1DashboardRebuildJob),
  106. typeof(Admin.NET.Plugin.AiDOP.Entity.SmartOps.AdoModuleDashboardRebuildJob),
  107. typeof(Admin.NET.Plugin.AiDOP.Entity.SmartOps.AdoMdpRebuildLock),
  108. typeof(AdoTenantMenuSuppression));
  109. AidopTenantMigration.MigrateOldTenantId(dbS4);
  110. AidopKpiMasterSeed.EnsureSeed(dbS4);
  111. AidopKpiMasterSeed.EnsureSeed(dbS4, 1300000000888);
  112. var kpiTenantIds = dbS4.Queryable<AdoSmartOpsKpiMaster>()
  113. .Select(x => x.TenantId)
  114. .Distinct()
  115. .ToList();
  116. foreach (var tenantId in kpiTenantIds.Where(x => x > 0))
  117. AidopKpiMasterSeed.EnsureSeed(dbS4, tenantId!.Value);
  118. AidopImprovementApprovalSeed.EnsureSeed(dbS4);
  119. Admin.NET.Plugin.AiDOP.Infrastructure.IqcInspBillFlowSeed.EnsureSeed(dbS4);
  120. Admin.NET.Plugin.AiDOP.Infrastructure.IpqcInspectionFlowSeed.EnsureSeed(dbS4);
  121. Admin.NET.Plugin.AiDOP.Infrastructure.S6ProcessInspectionFlowSeed.EnsureSeed(dbS4);
  122. Admin.NET.Plugin.AiDOP.Infrastructure.FqcInspBillFlowSeed.EnsureSeed(dbS4);
  123. }
  124. catch (Exception ex)
  125. {
  126. Trace.TraceWarning("Ai-DOP CodeFirst/S4 seed: " + ex);
  127. }
  128. if (!env.IsDevelopment())
  129. return;
  130. // 客户/物料/优先级等;远端若已是遗留表(已有主键),CodeFirst 会报 Multiple primary key,不可让启动失败。
  131. try
  132. {
  133. using var scope = app.ApplicationServices.CreateScope();
  134. var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  135. db.CodeFirst.InitTables(
  136. typeof(AdoS0CustMaster),
  137. typeof(AdoS0ItemMaster),
  138. typeof(AdoS0ItemSubstituteDetail),
  139. typeof(AdoS0PriorityCode),
  140. typeof(AdoS0ProductStructureOp),
  141. typeof(AdoS0StdOpMaster),
  142. typeof(AdoS0LineMaster),
  143. typeof(AdoS0MfgRoutingOpDetail),
  144. typeof(AdoS0MfgPersonSkillAssignment),
  145. typeof(AdoS0MfgWorkOrderControl),
  146. typeof(AdoS0MfgPersonSkill),
  147. typeof(AdoS0MfgLinePost),
  148. typeof(AdoS0MfgWorkCenter),
  149. typeof(AdoS0MfgLineMaterial),
  150. typeof(AdoS0ProcessFlowCard),
  151. typeof(AdoS0OrderScheduleCycle),
  152. typeof(AdoS0MfgElementParam),
  153. typeof(AdoS0MfgMaterialProcessElement),
  154. typeof(AdoS0MfgPreprocessElement),
  155. typeof(AdoS0MfgPreprocessElementParam),
  156. typeof(AdoS0ImageType),
  157. typeof(AdoS0QualitySegmentImage),
  158. typeof(AdoS0QmsQualityBaseType),
  159. typeof(AdoS0QmsFqcInspectionSpec),
  160. typeof(AdoS0QmsFqcInspectionSpecEntry),
  161. typeof(AdoS0QmsOqcInspectionSpec),
  162. typeof(AdoS0QmsOqcInspectionSpecEntry),
  163. typeof(AdoS0CategoryLeadTime),
  164. typeof(AdoS0MaterialPlanCycle),
  165. typeof(AdoS0SrmPurchase),
  166. typeof(AdoS8Exception),
  167. typeof(AdoS8ExceptionTimeline),
  168. typeof(AdoS8DecisionRecord),
  169. typeof(AdoS8Evidence),
  170. // S8-STANDARD-DATASET-HARD-CUTOVER-1:AdoS8AlertRule 已物理删除
  171. // (运行时权威一直是 AdoS8WatchRule;该表零 Runtime Consumer)。
  172. typeof(AdoS8SceneConfig),
  173. typeof(AdoS8NotificationLayer),
  174. typeof(AdoS8WatchRule),
  175. typeof(AdoS8RolePermissionConfig),
  176. typeof(AdoS8NotificationLog),
  177. typeof(AdoS8DashboardCellConfig),
  178. typeof(AdoS8ExceptionType),
  179. typeof(AdoS8DetectionLog),
  180. typeof(AdoS8RuleDetectionState),
  181. typeof(AdoS8Dimension),
  182. typeof(AdoS8DimensionNode),
  183. typeof(AdoS8ConfigDraft),
  184. typeof(AdoS8MonitorObject),
  185. typeof(AdoS8MonitorMetric),
  186. typeof(AdoS8OrderFlowOrder),
  187. typeof(AdoS8OrderFlowStage),
  188. typeof(AdoS8OrderFlowSnapshot),
  189. typeof(AdoS8OrderFlowSubstep),
  190. typeof(AdoS8OrderFlowSubstepUnit),
  191. typeof(AdoS8OrderFlowProcurementPivot),
  192. typeof(ContractReview),
  193. typeof(ContractReviewFlow),
  194. typeof(ProductDesign),
  195. typeof(ProductDesignBom),
  196. typeof(ProductDesignRouting)
  197. );
  198. AidopDimensionSeed.EnsureSeed(db);
  199. AidopMonitorDictionarySeed.EnsureSeed(db);
  200. }
  201. catch (Exception ex)
  202. {
  203. Trace.TraceWarning("Ai-DOP Development CodeFirst (S0/S8/Order demo tables): " + ex);
  204. }
  205. }
  206. }