赵新宇 2 weeks ago
parent
commit
c4ed4ffe5e
  1. 31
      .gitignore
  2. 6
      API/CherryTaskManager/CherryTaskManager.http
  3. 42
      API/CherryTaskManager/DataBaseMigration.csproj
  4. 2197
      API/CherryTaskManager/Migrations/20250526065431_Init.Designer.cs
  5. 1039
      API/CherryTaskManager/Migrations/20250526065431_Init.cs
  6. 2194
      API/CherryTaskManager/Migrations/JobDbContextModelSnapshot.cs
  7. 118
      API/CherryTaskManager/Program.cs
  8. 31
      API/CherryTaskManager/Properties/launchSettings.json
  9. 13
      API/CherryTaskManager/WeatherForecast.cs
  10. 8
      API/CherryTaskManager/appsettings.Development.json
  11. 55
      API/CherryTaskManager/appsettings.json
  12. 1020
      API/TaskManager.Contracts/Dtos/Dtos.cs
  13. 13
      API/TaskManager.Contracts/TaskManager.Contracts.csproj
  14. 767
      API/TaskManager.Entity/Entity.cs
  15. 13
      API/TaskManager.Entity/TaskManager.Entity.csproj
  16. 265
      API/TaskManager.EntityFramework/JobDbContext.cs
  17. 19
      API/TaskManager.EntityFramework/TaskManager.EntityFramework.csproj
  18. 68
      API/TaskManager.Job/Controllers/LogController.cs
  19. 175
      API/TaskManager.Job/Controllers/RecurringJobBaseController.cs
  20. 6
      API/TaskManager.Job/Controllers/RecurringJobInputPageController.cs
  21. 278
      API/TaskManager.Job/Controllers/RecurringJobOutPageController.cs
  22. 6
      API/TaskManager.Job/Controllers/SUPPLIER_BOM_CONTROLLER.cs
  23. 6
      API/TaskManager.Job/Controllers/SUPPLIER_CON_DATE_CONTROLLER.cs
  24. 6
      API/TaskManager.Job/Controllers/SUPPLIER_CON_MMRP_CONTROLLER.cs
  25. 6
      API/TaskManager.Job/Controllers/SUPPLIER_CON_PO_CONTROLLER.cs
  26. 15
      API/TaskManager.Job/Controllers/SUPPLIER_DEL_STATE_CONTROLLER.cs
  27. 6
      API/TaskManager.Job/Controllers/SUPPLIER_EMPLOYEE_CONTROLLER.cs
  28. 6
      API/TaskManager.Job/Controllers/SUPPLIER_INFO_CONTROLLER.cs
  29. 15
      API/TaskManager.Job/Controllers/SUPPLIER_INV_DATA_CONTROLLER.cs
  30. 15
      API/TaskManager.Job/Controllers/SUPPLIER_MRP_DATE_CONTROLLER.cs
  31. 14
      API/TaskManager.Job/Controllers/SUPPLIER_MRP_MONTH_CONTROLLER.cs
  32. 15
      API/TaskManager.Job/Controllers/SUPPLIER_MRP_STATE_CONTROLLER.cs
  33. 15
      API/TaskManager.Job/Controllers/SUPPLIER_MRP_WARNING_CONTROLLER.cs
  34. 14
      API/TaskManager.Job/Controllers/SUPPLIER_PO_CONTROLLER.cs
  35. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_ATTACHMENT_DATA_CONTROLLER.cs
  36. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_CPS_CONTROLLER.cs
  37. 14
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_CSCHEDUL_CONTROLLER.cs
  38. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_DATA_CONTROLLER.cs
  39. 5
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_ENVIRONMENT_CONTROLLER.cs
  40. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_FIRST_PASSYIELD_CONTROLLER.cs
  41. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_FLAW_CONTROLLER.cs
  42. 15
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_HSCHEDUL_CONTROLLER.cs
  43. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_MATERIAL_DATA_CONTROLLER.cs
  44. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_MATERIAL_STOCK_CONTROLLER.cs
  45. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE_CONTROLLER.cs
  46. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_OEE_TIME_DETAILS_CONTROLLER.cs
  47. 15
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_PLANING_CONTROLLER.cs
  48. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_PROCESS_CONTROLLER.cs
  49. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_PROCESS_EQUIPMENT_CONTROLLER.cs
  50. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_SCHEDULING_CONTROLLER.cs
  51. 6
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_STATION_FIRST_PASSYIELD_CONTROLLER.cs
  52. 15
      API/TaskManager.Job/Controllers/SUPPLIER_PRO_TSCHEDUL_CONTROLLER.cs
  53. 15
      API/TaskManager.Job/Controllers/SUPPLIER_RETURN_CONTROLLER.cs
  54. 17
      API/TaskManager.Job/Controllers/SUPPLIER_SA_WEEK_CONTROLLER.cs
  55. 14
      API/TaskManager.Job/Controllers/SUPPLIER_SINV_DATA_CONTROLLER.cs
  56. 185
      API/TaskManager.Job/Controllers/TOKEN_CONTROLLER.cs
  57. 578
      API/TaskManager.Job/Controllers/TaskConifgureController.cs
  58. 33
      API/TaskManager.Job/Controllers/WeatherForecastController.cs
  59. 24
      API/TaskManager.Job/TaskManager.Job.csproj
  60. 194
      API/Wood.Admin.WebApi/DataSeed.sql
  61. 63
      API/Wood.Admin.WebApi/Filter/ApiAuthorizeAttribute.cs
  62. 34
      API/Wood.Admin.WebApi/Filter/ApiExceptionFilter.cs
  63. 135
      API/Wood.Admin.WebApi/Filter/ApiPerformanceLoggingFilter.cs
  64. 117
      API/Wood.Admin.WebApi/Filter/ApiResponseWrapperFilter.cs
  65. 33
      API/Wood.Admin.WebApi/Middleware/FileServerMiddleware.cs
  66. 81
      API/Wood.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs
  67. 25
      API/Wood.Admin.WebApi/Middleware/ModelBindingMetadataProvider.cs
  68. 127
      API/Wood.Admin.WebApi/Other/AutoRouteConvention.cs
  69. 214
      API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs
  70. 61
      API/Wood.Admin.WebApi/Program.cs
  71. 22
      API/Wood.Admin.WebApi/Properties/launchSettings.json
  72. 346
      API/Wood.Admin.WebApi/Startup.cs
  73. 61
      API/Wood.Admin.WebApi/Wood.Admin.WebApi.csproj
  74. 9
      API/Wood.Admin.WebApi/appsettings.Development.json
  75. 32
      API/Wood.Admin.WebApi/appsettings.json
  76. BIN
      API/Wood.Admin.WebApi/wwwroot/template/用户信息导入模板.xlsx
  77. 74
      API/Wood.AutoJob/Attributes/CronAttribute.cs
  78. 75
      API/Wood.AutoJob/Attributes/DailyAtAttribute.cs
  79. 31
      API/Wood.AutoJob/Attributes/JobDetailAttribute.cs
  80. 72
      API/Wood.AutoJob/Attributes/PeriodMinutesAttribute.cs
  81. 73
      API/Wood.AutoJob/Attributes/PeriodSecondsAttribute.cs
  82. 279
      API/Wood.AutoJob/AutoJobCenter.cs
  83. 157
      API/Wood.AutoJob/AutoJobTask.cs
  84. 37
      API/Wood.AutoJob/Job/DBLogClearJob.cs
  85. 21
      API/Wood.AutoJob/Wood.AutoJob.csproj
  86. 27
      API/Wood.Cache/Wood.Cache.Interface/ICache.cs
  87. 14
      API/Wood.Cache/Wood.Cache.Interface/Wood.Cache.Interface.csproj
  88. 126
      API/Wood.Cache/Wood.MemoryCache/MemoryCacheImp.cs
  89. 20
      API/Wood.Cache/Wood.MemoryCache/Wood.MemoryCache.csproj
  90. 188
      API/Wood.Cache/Wood.RedisCache/RedisCacheImp.cs
  91. 20
      API/Wood.Cache/Wood.RedisCache/Wood.RedisCache.csproj
  92. 31
      API/Wood.Data.Repository/DataSeed/UserDataSeed.cs
  93. 234
      API/Wood.Data.Repository/DbContext/SqlSugarDbContext.cs
  94. 277
      API/Wood.Data.Repository/Extension/DatabaseExtension.cs
  95. 110
      API/Wood.Data.Repository/Extension/DatabasePageExtension.cs
  96. 169
      API/Wood.Data.Repository/Extension/RepositoryExtension.cs
  97. 146
      API/Wood.Data.Repository/Extension/SqlSugarPagedExtensions.cs
  98. 92
      API/Wood.Data.Repository/Repository.cs
  99. 35
      API/Wood.Data.Repository/UnitOfWork/IUnitOfWork.cs
  100. 79
      API/Wood.Data.Repository/UnitOfWork/SqlSugarUnitOfWork.cs

31
.gitignore

@ -0,0 +1,31 @@
# Build and Release Folders
bin-debug/
bin-release/
[Oo]bj/
[Bb]in/
# Other files and folders
.settings/
# Executables
*.swf
*.air
*.ipa
*.apk
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.
/Web/node_modules/
/Web/dist/
/Web/.vscode/
/Web/.vscode/
/Web/vite.config.js.timestamp*
/API/.vs/
/API/WoodAdmin.db
/API/Wood.Admin.WebApi/logs
/API/Wood.Admin.WebApi/wwwroot/uploads
bin/
obj/

6
API/CherryTaskManager/CherryTaskManager.http

@ -0,0 +1,6 @@
@CherryTaskManager_HostAddress = http://localhost:5014
GET {{CherryTaskManager_HostAddress}}/weatherforecast/
Accept: application/json
###

42
API/CherryTaskManager/DataBaseMigration.csproj

@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="EFCore.BulkExtensions" Version="9.0.1" />
<PackageReference Include="Hangfire" Version="1.8.20" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.20" />
<PackageReference Include="Hangfire.Core" Version="1.8.20" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="ValueInjecter" Version="3.2.0" />
<PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="9.103.8.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Entities\" />
<Folder Include="Migrations\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TaskManager.Contracts\TaskManager.Contracts.csproj" />
<ProjectReference Include="..\TaskManager.EntityFramework\TaskManager.EntityFramework.csproj" />
<ProjectReference Include="..\TaskManager.Entity\TaskManager.Entity.csproj" />
</ItemGroup>
</Project>

2197
API/CherryTaskManager/Migrations/20250526065431_Init.Designer.cs

File diff suppressed because it is too large

1039
API/CherryTaskManager/Migrations/20250526065431_Init.cs

File diff suppressed because it is too large

2194
API/CherryTaskManager/Migrations/JobDbContextModelSnapshot.cs

File diff suppressed because it is too large

118
API/CherryTaskManager/Program.cs

@ -0,0 +1,118 @@
using Hangfire;
using Hangfire.SqlServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using System;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using TaskManager.EntityFramework;
var builder = WebApplication.CreateBuilder(args);
// 从配置中获取连接字符串
var defaultConnection = builder.Configuration.GetConnectionString("Default");
builder.Services.AddHttpClient();
//builder.Services.AddScoped<LogController>();
//builder.Services.AddScoped<SUPPLIER_PRO_PLANING_CONTROLLER>();
//builder.Services.AddScoped<TaskConifgureController>();
//builder.Services.AddControllers()
// .AddJsonOptions(options =>
// {
// options.JsonSerializerOptions.Converters.Add(new CustomDateTimeConverter("yyyy-MM-dd HH:mm:ss"));
// options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
// });
// 添加服务到容器
builder.Services.AddControllers();
// 配置 JSON 序列化选项(从配置中读取策略)
var jsonNamingPolicy = builder.Configuration.GetValue<string>("JsonOptions:PropertyNamingPolicy");
if (jsonNamingPolicy == "CamelCase")
{
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
}
// 可选:支持其他命名策略(如 PascalCase)
else if (jsonNamingPolicy == "PascalCase")
{
// ...
}
//builder.Services.AddTransient<LogJobFilter>();
// 配置 DbContext 使用 SQL Server 连接字符串
builder.Services.AddDbContext<JobDbContext>(options =>
options.UseSqlServer(defaultConnection));
// 配置 Hangfire 使用 SQL Server 存储
builder.Services.AddHangfire(
configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170) // 建议显式设置兼容性版本
.UseSimpleAssemblyNameTypeSerializer() // 简化类型序列化(可选)
.UseRecommendedSerializerSettings() // 使用推荐的序列化设置(可选)
.UseSqlServerStorage(defaultConnection, new SqlServerStorageOptions
{
// 可从配置中读取 Hangfire 存储选项(如队列、重试策略等)
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
})
//.UseFilter(builder.Services.BuildServiceProvider().GetRequiredService<ILogger<LogJobFilter>>())
); // 添加日志过滤器(可选)
// 配置 Hangfire 服务器(可从配置中读取工作线程数等)
var workerCount = builder.Configuration.GetValue<int>("Hangfire:ServerOptions:WorkerCount", 10); // 默认值 10
builder.Services.AddHangfireServer(options =>
{
options.WorkerCount = workerCount;
// 可选:配置队列优先级
options.Queues = builder.Configuration.GetSection("Hangfire:ServerOptions:Queues").Get<string[]>() ?? new[] { "default" };
});
// 添加 Swagger 等其他服务...
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseHangfireDashboard();
// 配置中间件...
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
// 示例泛型方法

31
API/CherryTaskManager/Properties/launchSettings.json

@ -0,0 +1,31 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:23709",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5014",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

13
API/CherryTaskManager/WeatherForecast.cs

@ -0,0 +1,13 @@
namespace CherryTaskManager
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

8
API/CherryTaskManager/appsettings.Development.json

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

55
API/CherryTaskManager/appsettings.json

@ -0,0 +1,55 @@
{
"App": {
"CorsOrigins": "https://*.abc.com,http://localhost:9528,http://149.223.116.5:8088"
},
"ConnectionStrings": {
"Default": "Server=192.168.1.228;Database=TaskManager;User ID=sa;Password=ChangkeTec@2021;TrustServerCertificate=True"
},
//{
// "ConnectionStrings": {
// "DefaultConnection": "Server=localhost;Database=HANGFIRE_DEV;User ID=sa;Password=123456;TrustServerCertificate=True"
// },
// "Hangfire": {
// "ServerOptions": {
// "WorkerCount": 5 // 使线
// }
// }
//}
"Hangfire": {
"Dashboard": {
"Path": "/hangfire", // Dashboard 访
"RequireAuthorization": false //
},
"Server": {
"WorkerCount": 5, // 线
"Queues": [ "default", "critical", "background" ], //
"SchedulePollingInterval": 15000, //
"HeartbeatInterval": "00:00:15", //
"ServerTimeout": "00:05:00", //
"ServerCheckInterval": "00:01:00" //
},
"Storage": {
"JobExpirationCheckInterval": "00:01:00", //
"CountersAggregateInterval": "00:05:00", //
"QueuePollInterval": "00:00:15", //
"PrepareSchemaIfNecessary": true, //
"SlidingInvisibilityTimeout": "00:30:00", //
"UseRecommendedIsolationLevel": true, // 使
"EnableHeavyMigrations": false //
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Hangfire": "Information"
}
}
}
}

1020
API/TaskManager.Contracts/Dtos/Dtos.cs

File diff suppressed because it is too large

13
API/TaskManager.Contracts/TaskManager.Contracts.csproj

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

767
API/TaskManager.Entity/Entity.cs

@ -0,0 +1,767 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskManager.Entity
{
public interface IDoExecute
{
Task ExecuteAsync(string url, string path, string takName);
}
public class TaskConifgure
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long UId { get; set; }
/// <summary>
/// 加密用API路径
/// </summary>
public string Api { get; set; }
public string Corn { get; set; }
public string Module { get; set; }
public string Remark { get; set; }
public string TableName { get; set; }
public string TaskName { get; set; }
/// <summary>
/// 调用全路径
/// </summary>
public string Url { get; set; }
public bool IsAuto { get; set; }
}
public class TaskLog
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long UId { get; set; }
public string Info { get; set; }
public string Type { get; set; }
public string TaskName { get; set; }
public DateTime CreationTime { set; get; }
public string Remark { get; set; }
}
public class BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long UId { get; set; }
public bool WriteState { get; set; }
public bool ReadState { get; set; }
public DateTime CreationTime { get; set; }
public string Remark { get; set; }
}
public class CherryReadBaseEntity:BaseEntity
{
public string RequestDate { get; set; }
public string Id { get; set; }
public string TaskId { get; set; }
}
/// <summary>
/// 来料检验数据
/// </summary>
public class SUPPLIER_PRO_MATERIAL_STOCK:BaseEntity
{
}
/// <summary>
/// 排产数据
/// </summary>
public class SUPPLIER_PRO_SCHEDULING : BaseEntity
{
}
/// <summary>
/// 供应商基础信息
/// </summary>
public class SUPPLIER_INFO : BaseEntity
{
}
/// <summary>
/// 人员资质信息
/// </summary>
public class SUPPLIER_EMPLOYEE : BaseEntity
{
}
/// <summary>
/// BOM主数据
/// </summary>
public class SUPPLIER_BOM : BaseEntity
{
}
/// <summary>
/// 过程控制项质量数据
/// </summary>
public class SUPPLIER_PRO_CPS : BaseEntity
{
}
/// <summary>
/// 生产过程数据
/// </summary>
public class SUPPLIER_PRO_DATA : BaseEntity
{
}
/// <summary>
/// 产品一次合格率
/// </summary>
public class SUPPLIER_PRO_FIRST_PASSYIELD : BaseEntity
{
}
/// <summary>
/// 工位一次合格率
/// </summary>
public class SUPPLIER_PRO_STATION_FIRST_PASSYIELD : BaseEntity
{
}
/// <summary>
/// 缺陷业务数据
/// </summary>
public class SUPPLIER_PRO_FLAW : BaseEntity
{
}
/// <summary>
/// 环境业务数据
/// </summary>
public class SUPPLIER_PRO_ENVIRONMENT : BaseEntity
{
}
/// <summary>
/// 设备OEE达成率
/// </summary>
public class SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE : BaseEntity
{
}
/// <summary>
/// OEE时间明细
/// </summary>
public class SUPPLIER_PRO_OEE_TIME_DETAILS : BaseEntity
{
}
/// <summary>
/// 物料主数据
/// </summary>
public class SUPPLIER_PRO_MATERIAL_DATA : BaseEntity
{
}
/// <summary>
/// 附件类数据
/// </summary>
public class SUPPLIER_PRO_ATTACHMENT_DATA : BaseEntity
{
}
/// <summary>
/// 工艺装备
/// </summary>
public class SUPPLIER_PRO_PROCESS_EQUIPMENT : BaseEntity
{
}
/// <summary>
/// 工艺
/// </summary>
public class SUPPLIER_PRO_PROCESS : BaseEntity
{
}
/// <summary>
/// 整车月度生产计划-2
/// </summary>
public class SUPPLIER_PRO_PLANING : CherryReadBaseEntity
{
[JsonProperty("models")]
public string Models { get; set; }
[JsonProperty("quantity1")]
public decimal? Quantity1 { get; set; }
[JsonProperty("quantity2")]
public decimal? Quantity2 { get; set; }
[JsonProperty("startMonth")]
public string StartMonth { get; set; }
[JsonProperty("isDelete")]
public int IsDelete { get; set; }
[JsonProperty("updateByUser")]
public string UpdateByUser { get; set; }
[JsonProperty("pattern")]
public string Pattern { get; set; }
[JsonProperty("omterior")] // 可能是拼写错误,保留原始名称
public string Omterior { get; set; }
[JsonProperty("salseDepartment")] // 可能是拼写错误,保留原始名称
public string SalseDepartment { get; set; }
[JsonProperty("materialCode")]
public string MaterialCode { get; set; }
[JsonProperty("updateTime")]
public DateTime? UpdateTime { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("quantity3")]
public decimal? Quantity3 { get; set; }
[JsonProperty("releaseEdition")]
public string ReleaseEdition { get; set; }
[JsonProperty("quantity4")]
public decimal? Quantity4 { get; set; }
[JsonProperty("version")]
public int Version { get; set; }
[JsonProperty("quantity5")]
public decimal? Quantity5 { get; set; }
[JsonProperty("quantity6")]
public decimal? Quantity6 { get; set; }
[JsonProperty("createTime")]
public DateTime? CreateTime { get; set; }
[JsonProperty("plant")]
public string Plant { get; set; }
[JsonProperty("assembly")]
public string Assembly { get; set; }
[JsonProperty("createByUser")]
public string CreateByUser { get; set; }
}
/// <summary>
/// M+6月物料需求计划
/// </summary>
public class SUPPLIER_MRP_MONTH : CherryReadBaseEntity
{
public string ReleaseEdition { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string PlantId { get; set; }
public string PlantName { get; set; }
public string StartMonth { get; set; }
public decimal QuantityDemand1 { get; set; }
public decimal QuantityDemand2 { get; set; }
public decimal QuantityDemand3 { get; set; }
public decimal QuantityDemand4 { get; set; }
public decimal QuantityDemand5 { get; set; }
public decimal QuantityDemand6 { get; set; }
public decimal QuantityDemand7 { get; set; }
public decimal QuantityDemand8 { get; set; }
public decimal QuantityDemand9 { get; set; }
public decimal QuantityDemand10 { get; set; }
public decimal QuantityDemand11 { get; set; }
public decimal QuantityDemand12 { get; set; }
public string IsUpdate { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public string IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// M+6月物料需求计划风险确认
/// </summary>
public class SUPPLIER_CON_MMRP : BaseEntity
{
public string SupplierCode { get; set; }
public string ReleaseEdition { get; set; }
public string MaterialCode { get; set; }
public string PlantId { get; set; }
public string FeedbackResults { get; set; }
public string VentureType { get; set; }
public string VentureSpecific { get; set; }
public string Measures { get; set; }
public string StartMonth { get; set; }
public int QuantityMeet1 { get; set; }
public int QuantityMeet2 { get; set; }
public int QuantityMeet3 { get; set; }
public int QuantityMeet4 { get; set; }
public int QuantityMeet5 { get; set; }
public int QuantityMeet6 { get; set; }
public int QuantityMeet7 { get; set; }
public int QuantityMeet8 { get; set; }
public int QuantityMeet9 { get; set; }
public int QuantityMeet10 { get; set; }
public int QuantityMeet11 { get; set; }
public int QuantityMeet12 { get; set; }
}
/// <summary>
/// 日物料需求计划
/// </summary>
public class SUPPLIER_MRP_DATE : CherryReadBaseEntity
{
public string ReleaseEdition { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string PlantId { get; set; }
public string PlantName { get; set; }
public string StartDate { get; set; }
public int QuantityDemand1 { get; set; }
public int QuantityDemand2 { get; set; }
public int QuantityDemand3 { get; set; }
public int QuantityDemand4 { get; set; }
public int QuantityDemand5 { get; set; }
public int QuantityDemand6 { get; set; }
public int QuantityDemand7 { get; set; }
public int QuantityDemand8 { get; set; }
public int QuantityDemand9 { get; set; }
public int QuantityDemand10 { get; set; }
public int QuantityDemand11 { get; set; }
public int QuantityDemand12 { get; set; }
public int QuantityDemand13 { get; set; }
public int QuantityDemand14 { get; set; }
public int QuantityDemand15 { get; set; }
public int QuantityDemand16 { get; set; }
public int QuantityDemand17 { get; set; }
public int QuantityDemand18 { get; set; }
public int QuantityDemand19 { get; set; }
public int QuantityDemand20 { get; set; }
public int QuantityDemand21 { get; set; }
public int QuantityDemand22 { get; set; }
public int QuantityDemand23 { get; set; }
public int QuantityDemand24 { get; set; }
public int QuantityDemand25 { get; set; }
public int QuantityDemand26 { get; set; }
public int QuantityDemand27 { get; set; }
public int QuantityDemand28 { get; set; }
public int QuantityDemand29 { get; set; }
public int QuantityDemand30 { get; set; }
public int QuantityDemand31 { get; set; }
public string IsUpdate { get; set; }
public string CreateByUser { get; set; }
public string CreateTime { get; set; }
public string UpdateByUser { get; set; }
public string UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 日物料需求计划风险确认
/// </summary>
public class SUPPLIER_CON_DATE : BaseEntity
{
public string SupplierCode { get; set; }
public string ReleaseEdition { get; set; }
public string MaterialCode { get; set; }
public string PlantId { get; set; }
public string FeedbackResults { get; set; }
public string VentureType { get; set; }
public string VentureSpecific { get; set; }
public string Measures { get; set; }
public string StartDate { get; set; }
// QuantityMeet from 1 to 31
public int QuantityMeet1 { get; set; }
public int QuantityMeet2 { get; set; }
public int QuantityMeet3 { get; set; }
public int QuantityMeet4 { get; set; }
public int QuantityMeet5 { get; set; }
public int QuantityMeet6 { get; set; }
public int QuantityMeet7 { get; set; }
public int QuantityMeet8 { get; set; }
public int QuantityMeet9 { get; set; }
public int QuantityMeet10 { get; set; }
public int QuantityMeet11 { get; set; }
public int QuantityMeet12 { get; set; }
public int QuantityMeet13 { get; set; }
public int QuantityMeet14 { get; set; }
public int QuantityMeet15 { get; set; }
public int QuantityMeet16 { get; set; }
public int QuantityMeet17 { get; set; }
public int QuantityMeet18 { get; set; }
public int QuantityMeet19 { get; set; }
public int QuantityMeet20 { get; set; }
public int QuantityMeet21 { get; set; }
public int QuantityMeet22 { get; set; }
public int QuantityMeet23 { get; set; }
public int QuantityMeet24 { get; set; }
public int QuantityMeet25 { get; set; }
public int QuantityMeet26 { get; set; }
public int QuantityMeet27 { get; set; }
public int QuantityMeet28 { get; set; }
public int QuantityMeet29 { get; set; }
public int QuantityMeet30 { get; set; }
public int QuantityMeet31 { get; set; }
}
/// <summary>
/// 计划协议
/// </summary>
public class SUPPLIER_SA_WEEK : CherryReadBaseEntity
{
public string ScheduleAgreement { get; set; }
public string SerialNumber { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string PurchasingGroup { get; set; }
public string PlantId { get; set; }
public int QuantityDemand { get; set; }
public string DateReceived { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 采购订单
/// </summary>
public class SUPPLIER_PO : CherryReadBaseEntity
{
public string PurchaseOrder { get; set; }
public string SerialNumber { get; set; }
public string PlantId { get; set; }
public string PlantName { get; set; }
public string VoucherDate { get; set; }
public string Purchaser { get; set; }
public string Supplier { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public int QuantityDemand { get; set; }
public string MaterialUnit { get; set; }
public string DeliveryDate { get; set; }
public string DeliveryPlace { get; set; }
public int QuantityDelivery { get; set; }
public string Note { get; set; }
public string ItemType { get; set; }
public string TradeTerms { get; set; }
public string Country { get; set; }
public string Batch { get; set; }
public string CreateByUser { get; set; }
public string CreateTime { get; set; }
public string UpdateByUser { get; set; }
public string UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 采购订单风险确认
/// </summary>
public class SUPPLIER_CON_PO : BaseEntity
{
public string SupplierCode { get; set; }
public string PurchaseOrder { get; set; }
public string SerialNumber { get; set; }
public int QuantityMeet { get; set; }
public string FeedbackResults { get; set; }
public string VentureType { get; set; }
public string VentureSpecific { get; set; }
public string Measures { get; set; }
}
/// <summary>
/// 过焊装未过总装
/// </summary>
public class SUPPLIER_PRO_HSCHEDUL : CherryReadBaseEntity
{
public string Models { get; set; }
public string Vin { get; set; }
public string ProductionLineId { get; set; }
public string ProductionLineName { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string ProductionType { get; set; }
public string OnLineTime { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 过涂装未过总装
/// </summary>
public class SUPPLIER_PRO_TSCHEDUL : CherryReadBaseEntity
{
public string Models { get; set; }
public string Vin { get; set; }
public string ProductionLineId { get; set; }
public string ProductionLineName { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string OnLineTime { get; set; }
public string FinalWorkshop { get; set; }
public string FinalOnLineTime { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 排序供货
/// </summary>
public class SUPPLIER_PRO_CSCHEDUL : CherryReadBaseEntity
{
public string Models { get; set; }
public string Vin { get; set; }
public string ProductionLineId { get; set; }
public string ProductionLineName { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string SortDate { get; set; }
public string SortTime { get; set; }
public string OnLineDate { get; set; }
public string OnLineTime { get; set; }
public string ModelCategory { get; set; }
public string AssemblyMaterialCode { get; set; }
public string MotorMaterialCode { get; set; }
public string Plant { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 看板配送单
/// </summary>
public class SUPPLIER_DEL_STATE : CherryReadBaseEntity
{
public string DeliveryNumber { get; set; }
public string SerialNumber { get; set; }
public string SerialSrate { get; set; } // Matches input, may check for typo (e.g. SerialState?)
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string PlantId { get; set; }
public string ReceivingCrossings { get; set; }
public int QuantityDelivery { get; set; }
public string DataCreateTime { get; set; }
public string SupplierReceiveTime { get; set; }
public string RoadShippedTime { get; set; }
public string RoadReceiveTime { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 退货单
/// </summary>
public class SUPPLIER_RETURN : CherryReadBaseEntity
{
public string ReturnNumber { get; set; }
public string SerialNumber { get; set; }
public string SerialSrate { get; set; } // Matches input, possibly a typo (e.g. SerialState?)
public string PickUpLocation { get; set; }
public string DemandPickupTime { get; set; }
public string PickUpCrossings { get; set; }
public string Feedback { get; set; }
public string Plant { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public int QuantityDelivery { get; set; }
public string ReturnType { get; set; }
public string LotNumber { get; set; }
public string Judge { get; set; }
public string ReturnReason { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 奇瑞RDC共享库存
/// </summary>
public class SUPPLIER_INV_DATA : CherryReadBaseEntity
{
public string PlantId { get; set; }
public string PlantName { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public int QuantityCurrent { get; set; }
public string StockState { get; set; }
public string DataUpdateTime { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 供应商共享库存
/// </summary>
public class SUPPLIER_SINV_DATA : CherryReadBaseEntity
{
public string SupplierCode { get; set; }
public string SupplierName { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string MaterialType { get; set; }
public int QuantityCurrent { get; set; }
public int QuantityPlan { get; set; }
public string InventoryStatus { get; set; }
public int SafetyStock { get; set; }
public string ProductionCycle { get; set; }
public string DataUpdateTime { get; set; }
public string SupplierBatch { get; set; }
public string SupplieryxqDate { get; set; }
}
/// <summary>
/// 日MRP状态监控
/// </summary>
public class SUPPLIER_MRP_STATE : CherryReadBaseEntity
{
public string PlantId { get; set; }
public string PlantName { get; set; }
public string DemandSrate { get; set; } // Matches input, possibly a typo (e.g. DemandState?)
public string DemandType { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public string SummarySign { get; set; }
public string DateRequired { get; set; }
public int QuantityDemand { get; set; }
public string ConfirmTime { get; set; }
public int CreatQuantity { get; set; }
public int QuantityDelivery { get; set; }
public int QuantityReceive { get; set; }
public int QuantityInTransit { get; set; }
public int OnTimePercentage { get; set; }
public int SummaryCreatQuantity { get; set; }
public int SummaryQuantityDelivery { get; set; }
public int SummaryQuantityReceive { get; set; }
public int SummaryQuantityInTransit { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
/// <summary>
/// 日MRP预警推移
/// </summary>
public class SUPPLIER_MRP_WARNING : CherryReadBaseEntity
{
public string PlantId { get; set; }
public string MaterialCode { get; set; }
public string MaterialDescription { get; set; }
public int QuantityCurrent { get; set; }
public string ReckonDate { get; set; }
public int QuantityPlanned { get; set; }
public int QuantityPlannedDelivery { get; set; }
public int QuantityInTransit { get; set; }
public int DateGap { get; set; }
public int InventoryGap { get; set; }
public string CreateByUser { get; set; }
public DateTime CreateTime { get; set; }
public string UpdateByUser { get; set; }
public DateTime UpdateTime { get; set; }
public int IsDelete { get; set; }
public int Version { get; set; }
}
}

13
API/TaskManager.Entity/TaskManager.Entity.csproj

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

265
API/TaskManager.EntityFramework/JobDbContext.cs

@ -0,0 +1,265 @@

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Configuration;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaskManager.Entity;
using Wood.Util;
namespace TaskManager.EntityFramework
{
public class JobDbContext:DbContext
{
private const string ConnectionStringName = "DefaultConnection";
// 保存配置的字段
private readonly IConfiguration _configuration;
// 使用依赖注入的构造函数
public JobDbContext(DbContextOptions<JobDbContext> options, IConfiguration configuration)
: base(options)
{
_configuration = configuration;
// 设置命令超时时间
//this.Database.SetCommandTimeout(TimeSpan.FromMinutes(10));
}
public JobDbContext(DbContextOptions<JobDbContext> options)
: base(options)
{
}
public JobDbContext()
{
this.Database.SetCommandTimeout(System.TimeSpan.FromMinutes(50));
}
public JobDbContext(string strConn)
{
this.Database.SetCommandTimeout(System.TimeSpan.FromMinutes(50));
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 配置数据库连接字符串
//if (!optionsBuilder.IsConfigured)
//{
// // 从配置中获取连接字符串
// // var connectionString = _configuration.GetConnectionString("Server=192.168.1.228;Database=TaskManager;User ID=sa;Password=ChangkeTec@2021;TrustServerCertificate=True");
// //if (string.IsNullOrEmpty(connectionString))
// //{
// // throw new InvalidOperationException("无法从配置中获取数据库连接字符串");
// //}
// // 配置SQL Server连接
// optionsBuilder.UseSqlServer("Server=192.168.1.228;Database=TaskManager;User ID=sa;Password=ChangkeTec@2021;TrustServerCertificate=True");
//}
optionsBuilder.UseSqlServer(GlobalContext.SystemConfig.CustomerDb);
}
/// <summary>
/// 来料检验数据
/// </summary>
public DbSet<SUPPLIER_PRO_MATERIAL_STOCK> SupplierProMaterialStock { get; set; }
/// <summary>
/// 排产数据
/// </summary>
public DbSet<SUPPLIER_PRO_SCHEDULING> SupplierProScheduling { get; set; }
/// <summary>
/// 供应商基础信息
/// </summary>
public DbSet<SUPPLIER_INFO> SupplierInfo { get; set; }
/// <summary>
/// 人员资质信息
/// </summary>
public DbSet<SUPPLIER_EMPLOYEE> SupplierEmployee { get; set; }
/// <summary>
/// BOM主数据
/// </summary>
public DbSet<SUPPLIER_BOM> SupplierBom { get; set; }
/// <summary>
/// 过程控制项质量数据
/// </summary>
public DbSet<SUPPLIER_PRO_CPS> SupplierProCps { get; set; }
/// <summary>
/// 生产过程数据
/// </summary>
public DbSet<SUPPLIER_PRO_DATA> SupplierProData { get; set; }
/// <summary>
/// 产品一次合格率
/// </summary>
public DbSet<SUPPLIER_PRO_FIRST_PASSYIELD> SupplierProFirstPassYield { get; set; }
/// <summary>
/// 工位一次合格率
/// </summary>
public DbSet<SUPPLIER_PRO_STATION_FIRST_PASSYIELD> SupplierProStationFirstPassYield { get; set; }
/// <summary>
/// 缺陷业务数据
/// </summary>
public DbSet<SUPPLIER_PRO_FLAW> SupplierProFlaw { get; set; }
/// <summary>
/// 环境业务数据
/// </summary>
public DbSet<SUPPLIER_PRO_ENVIRONMENT> SupplierProEnvironment { get; set; }
/// <summary>
/// 设备OEE达成率
/// </summary>
public DbSet<SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE> SupplierProOeeAchievementRate { get; set; }
/// <summary>
/// OEE时间明细
/// </summary>
public DbSet<SUPPLIER_PRO_OEE_TIME_DETAILS> SupplierProOeeTimeDetails { get; set; }
/// <summary>
/// 物料主数据
/// </summary>
public DbSet<SUPPLIER_PRO_MATERIAL_DATA> SupplierProMaterialData { get; set; }
/// <summary>
/// 附件类数据
/// </summary>
public DbSet<SUPPLIER_PRO_ATTACHMENT_DATA> SupplierProAttachmentData { get; set; }
/// <summary>
/// 工艺装备
/// </summary>
public DbSet<SUPPLIER_PRO_PROCESS_EQUIPMENT> SupplierProProcessEquipment { get; set; }
/// <summary>
/// 工艺
/// </summary>
public DbSet<SUPPLIER_PRO_PROCESS> SupplierProProcess { get; set; }
/// <summary>
/// 整车月度生产计划-2
/// </summary>
public DbSet<SUPPLIER_PRO_PLANING> SupplierProPlaning { get; set; }
/// <summary>
/// M+6月物料需求计划
/// </summary>
public DbSet<SUPPLIER_MRP_MONTH> SupplierMrpMonth { get; set; }
/// <summary>
/// M+6月物料需求计划风险确认
/// </summary>
public DbSet<SUPPLIER_CON_MMRP> SupplierConMmrP { get; set; }
/// <summary>
/// 日物料需求计划
/// </summary>
public DbSet<SUPPLIER_MRP_DATE> SupplierMrpDate { get; set; }
/// <summary>
/// 日物料需求计划风险确认
/// </summary>
public DbSet<SUPPLIER_CON_DATE> SupplierConDate { get; set; }
/// <summary>
/// 计划协议
/// </summary>
public DbSet<SUPPLIER_SA_WEEK> SupplierSaWeek { get; set; }
/// <summary>
/// 采购订单
/// </summary>
public DbSet<SUPPLIER_PO> SupplierPo { get; set; }
/// <summary>
/// 采购订单风险确认
/// </summary>
public DbSet<SUPPLIER_CON_PO> SupplierConPo { get; set; }
/// <summary>
/// 过焊装未过总装
/// </summary>
public DbSet<SUPPLIER_PRO_HSCHEDUL> SupplierProHSchedul { get; set; }
/// <summary>
/// 过涂装未过总装
/// </summary>
public DbSet<SUPPLIER_PRO_TSCHEDUL> SupplierProTSchedul { get; set; }
/// <summary>
/// 排序供货
/// </summary>
public DbSet<SUPPLIER_PRO_CSCHEDUL> SupplierProCSchedul { get; set; }
/// <summary>
/// 看板配送单
/// </summary>
public DbSet<SUPPLIER_DEL_STATE> SupplierDelState { get; set; }
/// <summary>
/// 退货单
/// </summary>
public DbSet<SUPPLIER_RETURN> SupplierReturn { get; set; }
/// <summary>
/// 奇瑞RDC共享库存
/// </summary>
public DbSet<SUPPLIER_INV_DATA> SupplierInvData { get; set; }
/// <summary>
/// 供应商共享库存
/// </summary>
public DbSet<SUPPLIER_SINV_DATA> SupplierSInvData { get; set; }
/// <summary>
/// 日MRP状态监控
/// </summary>
public DbSet<SUPPLIER_MRP_STATE> SupplierMrpState { get; set; }
public DbSet<TaskLog> TaskLogs { get; set; }
public DbSet<TaskConifgure> TaskConifgure { get; set; }
//public DbSet<TaskConifgure> TaskConifgures { get; set; }
// 配置实体映射
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//modelBuilder.Entity<TaskConifgure>(entity =>
//{
// entity.ToTable("TaskConifgure");
//});
// 配置表名
// 其他配置...
}
}
}

19
API/TaskManager.EntityFramework/TaskManager.EntityFramework.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TaskManager.Entity\TaskManager.Entity.csproj" />
<ProjectReference Include="..\Wood.Util\Wood.Util.csproj" />
</ItemGroup>
</Project>

68
API/TaskManager.Job/Controllers/LogController.cs

@ -0,0 +1,68 @@

using Dapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class LogController:ControllerBase
{
private readonly JobDbContext _dbContext;
public LogController(JobDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<TaskLog>> GetAll()
{
var log = await _dbContext.TaskLogs.ToListAsync();
return log;
}
[HttpGet("AddError")]
public async Task<bool> AddError(string message,string taskname)
{
_dbContext.TaskLogs.Add(new TaskLog() { Info = message, Type = "错误",TaskName=taskname ,CreationTime=DateTime.Now});
var result =await _dbContext.SaveChangesAsync();
if (result > 0)
{
return true;
}
return false;
}
[HttpGet("AddInfo")]
public async Task<bool> AddInfo(string message, string taskname)
{
_dbContext.TaskLogs.Add(new TaskLog() { Info = message, Type = "记录", TaskName = taskname, CreationTime = DateTime.Now });
var result = await _dbContext.SaveChangesAsync();
if (result > 0)
{
return true;
}
return false;
}
}
//private readonly IServiceProvider _serviceProvider;
//public LogController(IServiceProvider serviceProvider)
//{
// _serviceProvider = serviceProvider;
//}
//public async Task<IEnumerable<Logs>> GetLogs()
//{
// var dbcontext= _serviceProvider.GetRequiredService<JobDbContext>();
// var connection=dbcontext.Database.GetDbConnection();
// connection.Query<Logs>("select top 10 * from logs");
//}
}

175
API/TaskManager.Job/Controllers/RecurringJobBaseController.cs

@ -0,0 +1,175 @@

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class RecurringJobBaseController :ControllerBase, IDoExecute
{
protected string appKey = "8EG566b9bedd2bf46d";
protected string appSecret = "48edc4425647425d87f806a1ba492580";
protected readonly HttpClient _httpClient;
protected readonly JobDbContext _jobDbContext;
protected string Path { set; get; } = "/v2/get/supplierProPlaning";
protected string Url { set; get; } = "/v2/get/supplierProPlaning";
protected virtual string TaskName { set; get; } = "SupplierProPlaning";
protected readonly LogController _logger;
public RecurringJobBaseController(
HttpClient httpClient,
JobDbContext jobDbContext,
LogController log
)
{
_httpClient = new HttpClient();
_jobDbContext = jobDbContext;
_logger = log;
}
/// <summary>
/// 提交给接口
/// </summary>
/// <param name="url"></param>
/// <param name="jsonData">录入DTOJson</param>
/// <returns>返回DTOJson</returns>
protected async Task<string> Post(string url, string path, string jsonData)
{
try
{
// 生成签名参数
string timeStamp = GetCurrentTimestamp();
string nonce = GenerateNonce();
var sign = GenerateSign(HttpMethod.Post.Method, path, appKey, appSecret, timeStamp, nonce, jsonData);
// 构建请求
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
request.Headers.Add("appKey", appKey);
request.Headers.Add("appSecret", appSecret);
request.Headers.Add("timestamp", timeStamp);
request.Headers.Add("sign", sign);
request.Headers.Add("nonce", nonce);
// 发送请求
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode(); // 抛出异常处理状态码
return await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
await _logger.AddError(ex.Message, this.TaskName);
//error = ex.Message;
return string.Empty;
}
}
private string GenerateSign(string method, string path, string appKey, string appSecret, string timestamp, string nonce, string jsonBody)
{
string paramStr = $"method={method.ToUpper()}&path={path}&appKey={appKey}&appSecret={appSecret}&timestamp={timestamp}&nonce={nonce}&jsonBody={jsonBody}";
return ComputeSHA512(paramStr);
}
private string ComputeSHA512(string input)
{
using (SHA512 sha512 = SHA512.Create())
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
byte[] hash = sha512.ComputeHash(bytes);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
builder.Append(hash[i].ToString("x2")); // "x2" 表示小写十六进制
}
return builder.ToString();
}
}
private string GetCurrentTimestamp()
{
return ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds).ToString();
}
private string GenerateNonce()
{
const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
int length = random.Next(10, 51);
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
private async Task BeforeExecuteAsync(string uid)
{
await _logger.AddInfo($"{TaskName}开始执行作业{uid}", TaskName);
}
private async Task AfterExecuteAsync(string uid)
{
await _logger.AddInfo($"{TaskName}结束执行作业{uid}", TaskName);
}
[HttpGet]
public async Task ExecuteAsync(string url, string path, string taskName)
{
var str = DateTime.Now.ToLongTimeString();
await BeforeExecuteAsync(str);
await DoExecutingAsync(url, path, taskName);
await AfterExecuteAsync(str);
}
protected async virtual Task DoExecutingAsync(string url, string path, string takName)
{
}
protected static string RemoveWhitespace(string input)
{
if (string.IsNullOrEmpty(input))
return input;
// 使用正则表达式移除空格和换行
return Regex.Replace(input, @"[\s]+", "");
}
}
}

6
API/TaskManager.Job/Controllers/RecurringJobInputPageController.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class RecurringJobInputPageController
{
}
}

278
API/TaskManager.Job/Controllers/RecurringJobOutPageController.cs

@ -0,0 +1,278 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Omu.ValueInjecter;
using System.Text.Json;
using System.Text.Json.Serialization;
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class RecurringJobOutPageController<T, ToutputDetial> : RecurringJobBaseController where T : CherryReadBaseEntity, new() where ToutputDetial : CherryReadBaseEntityDto
{
public RecurringJobOutPageController(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
public async Task<List<ToutputDetial>> FetchAllDataAsync(string inputdate)
{
var allData = new List<ToutputDetial>();
int totalItems = 0;
int pageSize = 0;
int currentPage = 1;
string date = !string.IsNullOrEmpty(inputdate) ? inputdate : DateTime.Now.ToString("yyyy-MM-dd");
// 首次请求获取总条数和分页信息
PagedResponse<ToutputDetial> firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, IsForce = true });
if (firstResponse == null || firstResponse.Code != 200)
{
await _logger.AddError("首次请求失败,无法获取分页信息。", TaskName);
return allData;
}
if (firstResponse.Data.Total == "0")
{
await _logger.AddError("首次请求失败,Total为0是否已经全部读取过。", TaskName);
return allData;
}
var readedcount = _jobDbContext.Set<T>().Where(p => p.RequestDate == inputdate).Count();
if (readedcount != int.Parse(firstResponse.Data.Total))//记录数不相等
{
var ids = _jobDbContext.Set<T>().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList();//已经同步的ID
totalItems = int.Parse(firstResponse.Data.Total);
pageSize = int.Parse(firstResponse.Data.PageSize);
List<T> pagefirstList = new List<T>();
if (readedcount > 0)
{
var listrows = firstResponse.Data.Rows.Where(p => !ids.Contains(p.Id));
foreach (var itm in firstResponse.Data.Rows)
{
T entity = new T();
entity.InjectFrom(itm);
entity.CreationTime = DateTime.Now;
pagefirstList.Add(entity);
allData.Add(itm);
}
}
else
{
foreach (var itm in firstResponse.Data.Rows)
{
T entity = new T();
entity.InjectFrom(itm);
entity.CreationTime = DateTime.Now;
pagefirstList.Add(entity);
allData.Add(itm);
}
}
_jobDbContext.BulkInsert(pagefirstList);
//Console.WriteLine($"总记录数: {totalItems}, 每页大小: {pageSize}");
// 计算总页数
int totalPages = (int)Math.Ceiling((double)totalItems / pageSize);
//Console.WriteLine($"总共需要请求 {totalPages} 页数据");
// 循环请求剩余页面
for (currentPage = 2; currentPage <= totalPages; currentPage++)
{
PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = currentPage, IsForce = true };
Console.WriteLine($"正在请求第 {currentPage} 页...");
PagedResponse<ToutputDetial> pageResponse = await GetPageAsync(pageinput);
if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0)
{
List<T> pageList = new List<T>();
//foreach (var itm in pageResponse.Data.Rows)
//{
// T entity = new T();
// entity.InjectFrom(itm);
// entity.CreationTime = DateTime.Now;
// pageList.Add(entity);
// allData.Add(itm);
//}
if (readedcount > 0)
{
var listrows = pageResponse.Data.Rows.Where(p => !ids.Contains(p.Id));
foreach (var itm in pageResponse.Data.Rows)
{
T entity = new T();
entity.InjectFrom(itm);
entity.CreationTime = DateTime.Now;
pageList.Add(entity);
allData.Add(itm);
}
}
else
{
foreach (var itm in pageResponse.Data.Rows)
{
T entity = new T();
entity.InjectFrom(itm);
entity.CreationTime = DateTime.Now;
pageList.Add(entity);
allData.Add(itm);
}
}
_jobDbContext.BulkInsert(pageList);
await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName);
}
else
{
await _logger.AddError($"第 {currentPage} 页未返回数据", TaskName);
}
// 简单的请求间隔,避免过于频繁
await Task.Delay(200);
}
await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName);
}
return allData;
}
private async Task<PagedResponse<ToutputDetial>> GetPageAsync(PAGE_DTO input)
{
try
{
var inputjson = JsonSerializer.Serialize(input,
new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true // 可选,用于格式化输出
}
);
inputjson = RemoveWhitespace(inputjson);
var content = await Post(Url, Path, inputjson);
if (!string.IsNullOrEmpty(content))
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = {
new JsonStringEnumConverter(), // 枚举转换
new CustomDateTimeConverter("yyyy-MM-dd HH:mm:ss") // 日期转换
}
};
return JsonSerializer.Deserialize<PagedResponse<ToutputDetial>>(content, options);
}
else
{
await _logger.AddError($"调用接口无返回值{Url}", TaskName);
return null;
}
}
catch (Exception ex)
{
await _logger.AddError($"调用接口无返回值错误{ex.Message}", TaskName);
return null;
}
//try
//{
// var url = $"{_apiUrl}?pageNum={pageNum}";
// var response = await _httpClient.GetAsync(url);
// if (response.IsSuccessStatusCode)
// {
// var content = await response.Content.ReadAsStringAsync();
// return JsonSerializer.Deserialize<PagedResponse<OUTPUT>>(content);
// }
// else
// {
// Console.WriteLine($"请求失败,状态码: {response.StatusCode}");
// return null;
// }
//}
//catch (Exception ex)
//{
// Console.WriteLine($"请求发生异常: {ex.Message}");
// return null;
//}
}
[HttpGet("Test")]
public async Task TestAsync(string url, string path, string taskName, string inputdate)
{
Url = url;
Path = path;
TaskName = taskName;
await FetchAllDataAsync(inputdate);
}
protected override async Task DoExecutingAsync(string url, string path, string takName)
{
Url = url;
Path = path;
TaskName = takName;
await FetchAllDataAsync(string.Empty);
}
// 反序列化时使用
}
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
private readonly string _format;
public CustomDateTimeConverter(string format)
{
_format = format;
}
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.ParseExact(reader.GetString(), _format, null);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_format));
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_BOM_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_BOM_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_CON_DATE_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_CON_DATE_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_CON_MMRP_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_CON_MMRP_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_CON_PO_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_CON_PO_CONTROLLER
{
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_DEL_STATE_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//看板配送单
public class SUPPLIER_DEL_STATE_CONTROLLER : RecurringJobOutPageController<SUPPLIER_DEL_STATE, SUPPLIER_DEL_STATE_DETAIL_DTO>
{
public SUPPLIER_DEL_STATE_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_EMPLOYEE_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_EMPLOYEE_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_INFO_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_INFO_CONTROLLER
{
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_INV_DATA_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//奇瑞RDC共享库存
public class SUPPLIER_INV_DATA_CONTROLLER : RecurringJobOutPageController<SUPPLIER_INV_DATA, SUPPLIER_INV_DATA_DETAIL_DTO>
{
public SUPPLIER_INV_DATA_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_MRP_DATE_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//日物料需求计划
public class SUPPLIER_MRP_DATE_CONTROLLER : RecurringJobOutPageController<SUPPLIER_MRP_DATE, SUPPLIER_MRP_DATE_DETAIL_DTO>
{
public SUPPLIER_MRP_DATE_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

14
API/TaskManager.Job/Controllers/SUPPLIER_MRP_MONTH_CONTROLLER.cs

@ -0,0 +1,14 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class SUPPLIER_MRP_MONTH_CONTROLLER : RecurringJobOutPageController<SUPPLIER_MRP_MONTH, SUPPLIER_MRP_MONTH_DETAIL_DTO>
{
public SUPPLIER_MRP_MONTH_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_MRP_STATE_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//日MRP状态监控
public class SUPPLIER_MRP_STATE_CONTROLLER : RecurringJobOutPageController<SUPPLIER_MRP_STATE, SUPPLIER_MRP_STATE_DETIAL_DTO>
{
public SUPPLIER_MRP_STATE_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_MRP_WARNING_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//日MRP预警推移
public class SUPPLIER_MRP_WARNING_CONTROLLER : RecurringJobOutPageController<SUPPLIER_MRP_WARNING, SUPPLIER_MRP_WARNING_DETAIL_DTO>
{
public SUPPLIER_MRP_WARNING_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

14
API/TaskManager.Job/Controllers/SUPPLIER_PO_CONTROLLER.cs

@ -0,0 +1,14 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class SUPPLIER_PO_CONTROLLER : RecurringJobOutPageController<SUPPLIER_PO, SUPPLIER_PO_DETAIL_DTO>
{
public SUPPLIER_PO_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_ATTACHMENT_DATA_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_ATTACHMENT_DATA_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_CPS_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_CPS_CONTROLLER
{
}
}

14
API/TaskManager.Job/Controllers/SUPPLIER_PRO_CSCHEDUL_CONTROLLER.cs

@ -0,0 +1,14 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_CSCHEDUL_CONTROLLER : RecurringJobOutPageController<SUPPLIER_PRO_CSCHEDUL, SUPPLIER_PRO_CSCHEDUL_DETAIL_DTO>
{
public SUPPLIER_PRO_CSCHEDUL_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_DATA_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_DATA_CONTROLLER
{
}
}

5
API/TaskManager.Job/Controllers/SUPPLIER_PRO_ENVIRONMENT_CONTROLLER.cs

@ -0,0 +1,5 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_ENVIRONMENT_CONTROLLER { }
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_FIRST_PASSYIELD_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_FIRST_PASSYIELD_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_FLAW_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_FLAW_CONTROLLER
{
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_PRO_HSCHEDUL_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//过焊装未过总装
public class SUPPLIER_PRO_HSCHEDUL_CONTROLLER : RecurringJobOutPageController<SUPPLIER_PRO_HSCHEDUL, SUPPLIER_PRO_HSCHEDUL_DETAIL_DTO>
{
public SUPPLIER_PRO_HSCHEDUL_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_MATERIAL_DATA_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_MATERIAL_DATA_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_MATERIAL_STOCK_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_MATERIAL_STOCK_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_OEE_TIME_DETAILS_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_OEE_TIME_DETAILS_CONTROLLER
{
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_PRO_PLANING_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//整车月度生产计划
public class SUPPLIER_PRO_PLANING_CONTROLLER : RecurringJobOutPageController<SUPPLIER_PRO_PLANING, SUPPLIER_PRO_PLANING_DETIAL_DTO>
{
public SUPPLIER_PRO_PLANING_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_PROCESS_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_PROCESS_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_PROCESS_EQUIPMENT_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_PROCESS_EQUIPMENT_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_SCHEDULING_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_SCHEDULING_CONTROLLER
{
}
}

6
API/TaskManager.Job/Controllers/SUPPLIER_PRO_STATION_FIRST_PASSYIELD_CONTROLLER.cs

@ -0,0 +1,6 @@
namespace TaskManager.Controllers
{
public class SUPPLIER_PRO_STATION_FIRST_PASSYIELD_CONTROLLER
{
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_PRO_TSCHEDUL_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//过涂装未过总装
public class SUPPLIER_PRO_TSCHEDUL_CONTROLLER : RecurringJobOutPageController<SUPPLIER_PRO_TSCHEDUL, SUPPLIER_PRO_TSCHEDUL_DETAIL_DTO>
{
public SUPPLIER_PRO_TSCHEDUL_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

15
API/TaskManager.Job/Controllers/SUPPLIER_RETURN_CONTROLLER.cs

@ -0,0 +1,15 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//退货单
public class SUPPLIER_RETURN_CONTROLLER : RecurringJobOutPageController<SUPPLIER_RETURN, SUPPLIER_RETURN_DETAIL_DTO>
{
public SUPPLIER_RETURN_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

17
API/TaskManager.Job/Controllers/SUPPLIER_SA_WEEK_CONTROLLER.cs

@ -0,0 +1,17 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
/// <summary>
/// 计划协议
/// </summary>
public class SUPPLIER_SA_WEEK_CONTROLLER : RecurringJobOutPageController<SUPPLIER_SA_WEEK, SUPPLIER_SA_WEEK_DETAIL_DTO>
{
public SUPPLIER_SA_WEEK_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

14
API/TaskManager.Job/Controllers/SUPPLIER_SINV_DATA_CONTROLLER.cs

@ -0,0 +1,14 @@
using TaskManager.Contracts.Dtos;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
public class SUPPLIER_SINV_DATA_CONTROLLER : RecurringJobOutPageController<SUPPLIER_SINV_DATA, SUPPLIER_SINV_DATA_DETAIL_DTO>
{
public SUPPLIER_SINV_DATA_CONTROLLER(HttpClient httpClient, JobDbContext jobDbContext, LogController log) : base(httpClient, jobDbContext, log)
{
}
}
}

185
API/TaskManager.Job/Controllers/TOKEN_CONTROLLER.cs

@ -0,0 +1,185 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace TaskManager.Controllers
{
public class TOKEN_CONTROLLER
{
private readonly HttpClient _httpClient;
private readonly string _appKey = "8EG566b9bedd2bf46d";
private readonly string _appSecret = "48edc4425647425d87f806a1ba492580"; // 若有密钥需传入
public TOKEN_CONTROLLER()
{
_httpClient = new HttpClient();
}
public async Task ExecuteAsync()
{
try
{
var retult = await GetTokenAsync("https://ediuat.mychery.com/prod-api/auth/public/login/appKey");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public async Task<string> GetTokenAsync(string tokenUrl)
{
var parameters = new
{
appKey = _appKey,
appSecret = _appSecret, // 按需传参
// 其他参数如 grant_type、scope 等根据接口要求调整
};
var content = new StringContent(
JsonConvert.SerializeObject(parameters),
Encoding.UTF8,
"application/json"
);
var response = await _httpClient.PostAsync(tokenUrl, content);
response.EnsureSuccessStatusCode(); // 抛异常处理错误
var responseBody = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<dynamic>(responseBody);
return result.data.access_token; // 假设返回字段为 access_token
}
}
//private readonly string _appKey = "8EG566b9bedd2bf46d";
//private readonly string _appSecret = "48edc4425647425d87f806a1ba492580";
//private readonly string _tokenEndpoint = "https://ediuat.mychery.com/prod-api/auth/public/login/appKey";
//private readonly HttpClient _httpClient;
//private readonly SemaphoreSlim _refreshLock = new SemaphoreSlim(1, 1);
//private string _currentToken;
//private DateTime _tokenExpiry;
//private bool _disposed;
//public TokenServiceController()
//{
// _httpClient = new HttpClient();
// _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//}
//public async Task<string> GetTokenAsync(CancellationToken cancellationToken = default)
//{
// // 检查令牌是否存在且未过期(提前60秒刷新以防止边缘情况)
// if (!string.IsNullOrEmpty(_currentToken) && _tokenExpiry > DateTime.UtcNow.AddSeconds(60))
// {
// return _currentToken;
// }
// // 等待获取锁,确保只有一个线程刷新令牌
// await _refreshLock.WaitAsync(cancellationToken);
// try
// {
// // 再次检查,避免其他线程已经刷新了令牌
// if (!string.IsNullOrEmpty(_currentToken) && _tokenExpiry > DateTime.UtcNow.AddSeconds(60))
// {
// return _currentToken;
// }
// // 调用认证API获取新令牌
// var tokenResponse = await FetchNewTokenAsync(cancellationToken);
// // 更新令牌和过期时间
// _currentToken = tokenResponse.AccessToken;
// _tokenExpiry = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn);
// return _currentToken;
// }
// finally
// {
// _refreshLock.Release();
// }
//}
//private async Task<TokenResponse> FetchNewTokenAsync(CancellationToken cancellationToken)
//{
// try
// {
// // 创建请求内容
// var requestBody = new
// {
// appKey = _appKey,
// appSecret = _appSecret
// };
// var content = new StringContent(
// JsonSerializer.Serialize(requestBody),
// Encoding.UTF8,
// "application/json");
// // 发送请求
// var response = await _httpClient.PostAsync(_tokenEndpoint, content, cancellationToken);
// response.EnsureSuccessStatusCode();
// // 解析响应
// var jsonResponse = await response.Content.ReadAsStringAsync(cancellationToken);
// var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(
// jsonResponse,
// new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
// if (tokenResponse == null || string.IsNullOrEmpty(tokenResponse.AccessToken))
// {
// throw new InvalidOperationException("Failed to retrieve access token.");
// }
// return tokenResponse;
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Token acquisition failed: {ex.Message}");
// throw;
// }
//}
//// 令牌响应模型
//private class TokenResponse
//{
// public string AccessToken { get; set; }
// public int ExpiresIn { get; set; } = 3600; // 默认1小时
//}
//public void Dispose()
//{
// Dispose(true);
// GC.SuppressFinalize(this);
//}
//protected virtual void Dispose(bool disposing)
//{
// if (!_disposed)
// {
// if (disposing)
// {
// _httpClient?.Dispose();
// _refreshLock?.Dispose();
// }
// _disposed = true;
// }
//}
//public Task ExecuteAsync()
//{
// throw new NotImplementedException();
//}
}

578
API/TaskManager.Job/Controllers/TaskConifgureController.cs

@ -0,0 +1,578 @@
using Hangfire;
using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Threading.Tasks;
using TaskManager.Controllers;
using TaskManager.Entity;
using TaskManager.EntityFramework;
namespace TaskManager.Controllers
{
//[ApiController]
//[Route("[controller]")]
public class TaskConifgureController :ControllerBase
{
private readonly JobDbContext _context;
private readonly IServiceProvider _builder;
private readonly IConfiguration _configuration;
public TaskConifgureController(JobDbContext context, IServiceProvider builder, IConfiguration configuration)
{
_builder = builder;
_context = context;
_configuration = configuration;
}
/// <summary>
/// 请除所有任务
/// </summary>
/// <returns></returns>
[HttpPost(Name = "ClearAllTask")]
public async Task ClearAllTask()
{
var tasks = await _context.TaskConifgure.ToListAsync();
foreach (var item in tasks)
{
RecurringJob.RemoveIfExists(item.TaskName);
}
}
/// <summary>
/// 执行铁定任务
/// </summary>
/// <param name="taskName"></param>
/// <returns></returns>
[HttpPost(Name = "ExecuteTask")]
public async Task ExecuteTask(string taskName)
{
var first=await _context.TaskConifgure.FirstOrDefaultAsync(p => p.TaskName == taskName);
var url = first.Url;
var path = first.Api;
var controller = _builder.GetRequiredService<SUPPLIER_PRO_PLANING_CONTROLLER>();
await controller.ExecuteAsync(url,path, taskName);
}
/// <summary>
/// 执行铁定任务
/// </summary>
/// <param name="taskName"></param>
/// <returns></returns>
[HttpGet(Name = "testTask")]
public async Task testTask(string taskName)
{
var first = await _context.TaskConifgure.FirstOrDefaultAsync(p => p.TaskName == taskName);
var url = first.Url;
var path = first.Api;
var controller = _builder.GetRequiredService<SUPPLIER_PRO_PLANING_CONTROLLER>();
await controller.TestAsync(url, path, taskName,"2025-04-21");
}
public async Task RefreshTaskConfig()
{
// 从数据库加载所有任务配置
var tasks = _context.TaskConifgure.Where(p => p.IsAuto == true && !string.IsNullOrEmpty(p.Corn)
&& !string.IsNullOrEmpty(p.Api) && !string.IsNullOrEmpty(p.Url)).ToList();
var delTasks = _context.TaskConifgure.Where(p => p.IsAuto == false || string.IsNullOrEmpty(p.Corn)
|| string.IsNullOrEmpty(p.Api) || string.IsNullOrEmpty(p.Url)
).ToList();
foreach (var task in tasks)
{
var url = task.Url;
var path = task.Api;
switch (task.TaskName)
{
//case "来料检验数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_MATERIAL_STOCK_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url,path,task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "排产数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_SCHEDULING_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "供应商基础信息":
// RecurringJob.AddOrUpdate<SUPPLIER_INFO_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "人员资质信息":
// RecurringJob.AddOrUpdate<SUPPLIER_EMPLOYEE_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "BOM主数据":
// RecurringJob.AddOrUpdate<SUPPLIER_BOM_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "过程控制项质量数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_CPS_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "生产过程数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_DATA_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "产品一次合格率":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_FIRST_PASSYIELD_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "工位一次合格率":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_STATION_FIRST_PASSYIELD_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "缺陷业务数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_FLAW_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "环境业务数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_ENVIRONMENT_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "设备OEE达成率":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_OEE_ACHIEVEMENT_RATE_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "OEE时间明细":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_OEE_TIME_DETAILS_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "物料主数据":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_MATERIAL_DATA_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "工艺装备":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_PROCESS_EQUIPMENT_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
//case "工艺":
// RecurringJob.AddOrUpdate<SUPPLIER_PRO_PROCESS_CONTROLLER>(
// task.TaskName,
// x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
// task.Corn,
// TimeZoneInfo.Local
// );
// break;
case "整车月度生产计划1":
RecurringJob.AddOrUpdate<SUPPLIER_PRO_PLANING_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "M+6月物料需求计划1":
RecurringJob.AddOrUpdate<SUPPLIER_MRP_MONTH_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "整车月度生产计划2":
RecurringJob.AddOrUpdate<SUPPLIER_PRO_PLANING_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "M+6月物料需求计划2":
RecurringJob.AddOrUpdate<SUPPLIER_MRP_MONTH_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "日物料需求计划":
RecurringJob.AddOrUpdate<SUPPLIER_MRP_DATE_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "计划协议":
RecurringJob.AddOrUpdate<SUPPLIER_SA_WEEK_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "采购订单":
RecurringJob.AddOrUpdate<SUPPLIER_PO_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "过焊装未过总装":
RecurringJob.AddOrUpdate<SUPPLIER_PRO_HSCHEDUL_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "过涂装未过总装":
RecurringJob.AddOrUpdate<SUPPLIER_PRO_TSCHEDUL_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "排序供货":
RecurringJob.AddOrUpdate<SUPPLIER_PRO_CSCHEDUL_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "看板配送单":
RecurringJob.AddOrUpdate<SUPPLIER_DEL_STATE_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "退货单":
RecurringJob.AddOrUpdate<SUPPLIER_RETURN_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "奇瑞RDC共享库存":
RecurringJob.AddOrUpdate<SUPPLIER_INV_DATA_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "日MRP状态监控":
RecurringJob.AddOrUpdate<SUPPLIER_MRP_STATE_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "日MRP预警推移":
RecurringJob.AddOrUpdate<SUPPLIER_MRP_WARNING_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "M+6月物料需求计划风险确认":
RecurringJob.AddOrUpdate<SUPPLIER_CON_MMRP_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "日物料需求计划风险确认":
RecurringJob.AddOrUpdate<SUPPLIER_CON_DATE_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "采购订单风险确认":
RecurringJob.AddOrUpdate<SUPPLIER_CON_PO_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "供应商共享库存-上午":
RecurringJob.AddOrUpdate<SUPPLIER_SINV_DATA_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
case "供应商共享库存-晚上":
RecurringJob.AddOrUpdate<SUPPLIER_SINV_DATA_CONTROLLER>(
task.TaskName,
x => ((IDoExecute)x).ExecuteAsync(url, path, task.TaskName),
task.Corn,
TimeZoneInfo.Local
);
break;
}
}
foreach (var task in delTasks)
{
switch (task.TaskName)
{
case "来料检验数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "排产数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "供应商基础信息":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "人员资质信息":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "BOM主数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "过程控制项质量数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "生产过程数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "产品一次合格率":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "工位一次合格率":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "缺陷业务数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "环境业务数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "设备OEE达成率":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "OEE时间明细":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "物料主数据":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "工艺装备":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "工艺":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "整车月度生产计划1":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "M+6月物料需求计划1":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "整车月度生产计划2":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "M+6月物料需求计划2":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "日物料需求计划":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "计划协议":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "采购订单":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "过焊装未过总装":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "过涂装未过总装":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "排序供货":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "看板配送单":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "退货单":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "奇瑞RDC共享库存":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "日MRP状态监控":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "日MRP预警推移":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "M+6月物料需求计划风险确认":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "日物料需求计划风险确认":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "采购订单风险确认":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "供应商共享库存-上午":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
case "供应商共享库存-晚上":
// 移除指定的定时任务
RecurringJob.RemoveIfExists(task.TaskName);
break;
}
}
}
// 使用 Hangfire 注册定时任务
// Console.WriteLine($"已注册定时任务: {task.TaskName}, Cron: {task.Corn}");
}
}

33
API/TaskManager.Job/Controllers/WeatherForecastController.cs

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace TaskManager.Controllers
{
//[ApiController]
//[Route("[controller]")]
//public class WeatherForecastController : ControllerBase
//{
// private static readonly string[] Summaries = new[]
// {
// "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
// };
// private readonly ILogger<WeatherForecastController> _logger;
// public WeatherForecastController(ILogger<WeatherForecastController> logger)
// {
// _logger = logger;
// }
// [HttpGet(Name = "GetWeatherForecast")]
// public IEnumerable<WeatherForecast> Get()
// {
// return Enumerable.Range(1, 5).Select(index => new WeatherForecast
// {
// Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
// TemperatureC = Random.Shared.Next(-20, 55),
// Summary = Summaries[Random.Shared.Next(Summaries.Length)]
// })
// .ToArray();
// }
//}
}

24
API/TaskManager.Job/TaskManager.Job.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.20" />
<PackageReference Include="Hangfire.Core" Version="1.8.20" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
<PackageReference Include="ValueInjecter" Version="3.2.0" />
<PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="9.103.8.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="C:\迅雷下载\Admin.NET-next\Admin.NET\TaskManager.Contracts\TaskManager.Contracts.csproj" />
<ProjectReference Include="C:\迅雷下载\Admin.NET-next\Admin.NET\TaskManager.EntityFramework\TaskManager.EntityFramework.csproj" />
<ProjectReference Include="C:\迅雷下载\Admin.NET-next\Admin.NET\TaskManager.Entity\TaskManager.Entity.csproj" />
</ItemGroup>
</Project>

194
API/Wood.Admin.WebApi/DataSeed.sql

@ -0,0 +1,194 @@
--
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1300000002, 1300000002, 1300000001, NULL, '2025-01-19 13:13:56.691');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1300000003, 1300000003, 1300000002, NULL, '2025-01-19 13:13:56.691');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1882329230927339520, 1881982901915099136, 1300000001, 0, '2025-01-23 15:27:15.2961165');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1882356958271512576, 1882356958254735360, 1882356955843010560, 1300000001, '2025-01-23 17:17:26.0105013');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1884805524378230784, 1300000001, 1300000001, 0, '2025-01-30 11:27:09.6628944');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1884918908515917824, 1884918908272648192, 1300000001, 0, '2025-01-30 18:57:42.547');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1884918908520112128, 1884918908272648193, 1300000001, 0, '2025-01-30 18:57:42.548');
INSERT INTO "SysUserBelongRole" ("Id", "UserId", "RoleId", "CreateUserId", "CreateTime") VALUES (1886588408239890432, 1881984359129554944, 1300000002, 0, '2025-02-04 09:31:42.2990032');
--
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000001, 'gu+qpKMTvW6Z8ooVOfSgzQ==', 'aUyhQl7o7CJFvePL', 1300000001, 0, '2025-02-04 13:55:41.8323838', 9999, 32, '2025-01-30 08:34:49.288', '2025-02-04 13:55:41.6049409', 'superadmin', '超级管理员', '超级管理员', 1, '1992-01-01 01:01:01', '', '123456', '738CC2E1CF6C468B8C8153AEFCD261E9', 1300000000, 1, '', 1300000001, '2025-01-19 13:13:56.649', NULL, '2025-02-04 13:55:41.8328374', NULL, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000002, 'gu+qpKMTvW6Z8ooVOfSgzQ==', '384DjuHkbZm6FW2Q', 1881265290692665344, 1881948006849323008, NULL, 9, 0, NULL, NULL, 'admin', '管理员', '管理员', 1, '1992-01-02 00:00:00', '', '123456', NULL, 1300000000, 1, '', 1300000001, '2025-01-19 13:13:56.650', NULL, '2025-01-22 15:47:37.954337', 1300000001, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000003, 'gu+qpKMTvW6Z8ooVOfSgzQ==', 'GwvjCfaiFnW5ztfI', 1300000001, 0, NULL, 0, 0, NULL, NULL, 'user1', '用户1', '用户1', 1, '1992-01-01 01:01:01.000', '', '', NULL, 1300000000, 1, '', 1300000001, '2025-01-19 13:13:56.651', NULL, '2025-01-22 09:13:07.5703432', 1300000001, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881982901915099136, 'gu+qpKMTvW6Z8ooVOfSgzQ==', '+}HhxENLnwBlg]1T', 1881265290692665344, 1881950674254700544, NULL, 0, 0, NULL, NULL, 'user2', '用户2', '测试用户2', 1, '2025-01-01 00:00:00.000', '', '1234563', '7783596F18544438936EE27596210D1A', 1300000000, 1, NULL, 1300000001, '2025-01-22 16:31:04.0252115', 1300000001, '2025-01-23 15:27:15.285', 1300000001, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881984359129554944, 'gu+qpKMTvW6Z8ooVOfSgzQ==', 'FkTN`kgfXrzAi9R*', 1300000001, 1881948006849323008, '2025-02-04 13:55:41.0875974', 0, 5, '2025-02-04 09:24:01.608', '2025-02-04 11:39:42.3846371', 'user3', '用户3', '用户3', 1, '2024-08-01 00:00:00', '', '123', '6D2A4E33108F40CCBA4E1D856CC87FD1', 1300000000, 1, NULL, 1300000001, '2025-01-22 16:36:51.452712', 1300000001, '2025-02-04 13:55:41.0881672', NULL, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882356958254735360, 'gu+qpKMTvW6Z8ooVOfSgzQ==', 't`2o3qFBS*+yb,MZ', 1882356955780096000, 0, NULL, 991, 0, NULL, NULL, 'UUSER001', '测试用户111', '测试用户111', 0, '2025-01-23 17:17:26.0039908', NULL, NULL, NULL, 1882356955796873216, 1, NULL, 1300000001, '2025-01-23 17:17:26.0059504', 1300000001, NULL, NULL, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884918908272648192, '', '', 1881265290692665344, 0, NULL, 0, 0, NULL, NULL, 'zhangsan', '张三', '张三', 1, '1900-01-01 00:00:00.000', '1F@foxconn.com', '123456', NULL, 1300000000, 1, NULL, 1300000001, '2025-01-30 18:57:42.491', 1300000001, NULL, NULL, '0');
INSERT INTO "SysUser" ("Id", "Password", "Salt", "OrgId", "PositionId", "LastVisit", "AccountType", "LoginCount", "FirstVisit", "PreviousVisit", "UserName", "RealName", "NickName", "Gender", "Birthday", "Email", "Mobile", "Avatar", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884918908272648193, '', '', 1881265290692665344, 0, NULL, 0, 0, NULL, NULL, 'lisi', '李四', '李四', 0, '1900-01-01 00:00:00.000', '1F@foxconn.com', '1F456789', NULL, 1300000000, 1, NULL, 1300000001, '2025-01-30 18:57:42.493', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysTenant" ("Id", "TenantName", "OrgId", "Sort", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000000, '默认租户', 1300000001, 10, 1, NULL, 1300000001, '2025-01-19 13:13:56.6721406', NULL, '2025-01-23 17:02:41.7352215', 1300000001, '0');
INSERT INTO "SysTenant" ("Id", "TenantName", "OrgId", "Sort", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882356955796873216, '测试租户1', 1882356955780096000, 20, 1, NULL, 1300000001, '2025-01-23 17:17:25.4199306', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysRole" ("Id", "RoleName", "FormCode", "DataScopeType", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000001, '管理员', 'admin_role', 2, 10, 1300000000, 1, NULL, 1300000001, '2025-01-19 13:13:56.681', NULL, '2025-01-21 18:58:09.1905823', 1300000001, '0');
INSERT INTO "SysRole" ("Id", "RoleName", "FormCode", "DataScopeType", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000002, '普通用户', 'normal_role', 8, 20, 1300000000, 1, NULL, 1300000001, '2025-01-19 13:13:56.682', NULL, '2025-02-04 09:34:12.2207514', 1300000001, '0');
INSERT INTO "SysRole" ("Id", "RoleName", "FormCode", "DataScopeType", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882356955843010560, '租管-质量测试部', 'zlcsb_role', 2, 30, 1882356955796873216, 1, NULL, 1300000001, '2025-01-23 17:17:25.431329', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysPosition" ("Id", "PositionName", "FormCode", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881948006849323008, '董事长', 'dsz', 10, 1300000000, 1, NULL, 1300000001, '2025-01-22 14:12:24.3929755', 1300000001, '2025-01-22 14:21:50.3038159', 1300000001, '0');
INSERT INTO "SysPosition" ("Id", "PositionName", "FormCode", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881950674254700544, '总经理', 'zjl', 20, 1300000000, 1, NULL, 1300000001, '2025-01-22 14:23:00.3525383', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysOrg" ("Id", "ParentId", "OrgName", "FormCode", "ShortName", "Telephone", "Email", "PrincipalUserId", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000001, 0, '系统默认', 'default_org', '系统默认', '', '', 1300000002, 10, 1300000000, 1, NULL, 1300000001, '2025-01-19 13:13:56.5661473', NULL, '2025-01-21 08:19:18.4835719', 1300000001, '0');
INSERT INTO "SysOrg" ("Id", "ParentId", "OrgName", "FormCode", "ShortName", "Telephone", "Email", "PrincipalUserId", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881265290692665344, 1300000001, '机构1', 'jg1', 'test01', '', '', 1300000002, 21, 1300000000, 1, NULL, 1300000001, '2025-01-20 16:59:32.1765571', 1300000001, '2025-01-21 08:19:18.4835719', 1300000001, '0');
INSERT INTO "SysOrg" ("Id", "ParentId", "OrgName", "FormCode", "ShortName", "Telephone", "Email", "PrincipalUserId", "Sort", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882356955780096000, 0, '质量测试部', 'zlcsb', '质量测试部', NULL, NULL, 0, 31, 1882356955796873216, 1, NULL, 1300000001, '2025-01-23 17:17:25.4271006', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917632, 1300000003, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917633, 1300000001, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917634, 1300000002, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917635, 1886587042893275136, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917636, 1886305270632685568, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917637, 1886587128931033088, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917638, 1884778107420942336, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886589037070917639, 1884778243870040064, 1300000002, 1300000000, 1, NULL, 1300000001, '2025-02-04 09:34:12.224', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794611613696, 1300000001, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.540', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794620002304, 1300000002, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.542', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196608, 1886587042893275136, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.542', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196609, 1886305270632685568, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196610, 1886587128931033088, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196611, 1300000003, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196612, 1881222457235480576, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196613, 1881549686175834112, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196614, 1881549758976368640, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196615, 1881549837590208512, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196616, 1881549892451704832, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196617, 1881503648907927552, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196618, 1881550091223965696, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196619, 1881550170370482176, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196620, 1881550231213056000, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196621, 1881550282572308480, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196622, 1881550362545102848, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196623, 1881662579596730368, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196624, 1881662811004870656, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196625, 1881662934095110144, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196626, 1881662997173248000, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196627, 1881663062772162560, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196628, 1881663313054670848, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794624196629, 1884857795430457344, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.543', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390912, 1884857884613943296, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390913, 1881943420327567360, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390914, 1881943540813144064, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390915, 1881943652230635520, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390916, 1881943716881637376, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390917, 1881943791406030848, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390918, 1884778107420942336, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390919, 1884778243870040064, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390920, 1886302722643337216, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390921, 1886305880748728320, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390922, 1886305957932310528, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390923, 1886306037544394752, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390924, 1886306151197450240, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390925, 1886369812943347712, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891794794628390926, 1886613824367370240, 1300000001, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:20:01.544', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938251513856, 1300000001, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.204', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938255708160, 1300000002, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.206', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902464, 1886587042893275136, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.206', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902465, 1886305270632685568, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902466, 1886587128931033088, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902467, 1300000003, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902468, 1881222457235480576, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902469, 1881549686175834112, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902470, 1881549758976368640, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902471, 1881549837590208512, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902472, 1881549892451704832, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902473, 1881503648907927552, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902474, 1881550091223965696, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902475, 1881550170370482176, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902476, 1881550231213056000, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902477, 1881550282572308480, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902478, 1881550362545102848, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902479, 1881662579596730368, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902480, 1881662811004870656, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902481, 1881662934095110144, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902482, 1881662997173248000, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902483, 1881663062772162560, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902484, 1881663313054670848, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938259902485, 1884857795430457344, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096768, 1884857884613943296, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.207', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096769, 1881943420327567360, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096770, 1881943540813144064, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096771, 1881943652230635520, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096772, 1881943716881637376, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096773, 1881943791406030848, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096774, 1884778107420942336, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096775, 1884778243870040064, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096776, 1886302722643337216, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096777, 1886305880748728320, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096778, 1886305957932310528, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096779, 1886306037544394752, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096780, 1886306151197450240, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096781, 1886369812943347712, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenuAuthorize" ("Id", "MenuId", "RoleId", "TenantId", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1891795938264096782, 1886613824367370240, 1882356955843010560, 1300000000, 1, NULL, 1300000001, '2025-02-18 18:24:34.208', 1300000001, NULL, NULL, '0');
--
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000001, 0, '工作台', NULL, '/', 'Layout', 'el-Odometer', '/dashboard', '0', '0', '0', NULL, NULL, 10, 1, 1, NULL, 1300000001, '2025-01-19 13:13:56.700', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000002, 1300000001, '主页', 'dashboardIndex', '/dashboard', '/dashboard/index.vue', 'el-Aim', NULL, '0', '0', '1', NULL, NULL, 10, 2, 1, NULL, 1300000001, '2025-01-19 13:13:56.702', 1300000001, '2025-01-30 19:27:01.3156973', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000003, 0, '系统管理', NULL, '/system', 'Layout', 'el-Setting', NULL, '0', '0', '0', NULL, NULL, 9999, 1, 1, NULL, 1300000001, '2025-01-19 13:13:56.702', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1300000004, 1883382946094784512, '菜单管理', 'menuIndex', '/platform/menuManage', '/system/menu/index.vue', 'el-Guide', NULL, '1', '0', '0', NULL, NULL, 10, 2, 1, NULL, 1300000001, '2025-01-19 13:13:56.702', 1300000001, '2025-01-30 19:27:23.3832916', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881222457235480576, 1300000003, '机构管理', 'orgIndex', '/system/orgManage', '/system/org/index.vue', 'fa-sitemap', '', '1', '0', '0', '', '', 10009, 2, 1, NULL, 1300000001, '2025-01-20 14:09:19.8848362', 1300000001, '2025-01-30 19:25:06.9356138', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881503648907927552, 1300000003, '角色管理', 'roleIndex', '/system/rolemanage', '/system/role/index.vue', 'el-Avatar', '', '1', '0', '0', '', '', 10019, 2, 1, NULL, 1300000001, '2025-01-21 08:46:41.2039094', 1300000001, '2025-01-30 19:25:20.6951188', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549094716055552, 1300000004, '查询', '', '', '', '', '', '1', '0', '0', '', 'menuIndex:page', 10029, 3, 1, NULL, 1300000001, '2025-01-21 11:47:16.3290049', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549322898776064, 1300000004, '新增', '', '', '', '', '', '1', '0', '0', '', 'menuIndex:add', 10039, 3, 1, NULL, 1300000001, '2025-01-21 11:48:10.7325507', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549479568613376, 1300000004, '编辑', '', '', '', '', '', '1', '0', '0', '', 'menuIndex:edit', 10049, 3, 1, NULL, 1300000001, '2025-01-21 11:48:48.0853661', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549545742147584, 1300000004, '删除', '', '', '', '', '', '1', '0', '0', '', 'menuIndex:delete', 10059, 3, 1, NULL, 1300000001, '2025-01-21 11:49:03.8620944', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549686175834112, 1881222457235480576, '查询', '', '', '', '', '', '1', '0', '0', '', 'orgIndex:page', 10069, 3, 1, NULL, 1300000001, '2025-01-21 11:49:37.3442189', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549758976368640, 1881222457235480576, '新增', '', '', '', '', '', '1', '0', '0', '', 'orgIndex:add', 10079, 3, 1, NULL, 1300000001, '2025-01-21 11:49:54.7016825', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549837590208512, 1881222457235480576, '编辑', '', '', '', '', '', '1', '0', '0', '', 'orgIndex:edit', 10089, 3, 1, NULL, 1300000001, '2025-01-21 11:50:13.4445591', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881549892451704832, 1881222457235480576, '删除', '', '', '', '', '', '1', '0', '0', '', 'orgIndex:delete', 10099, 3, 1, NULL, 1300000001, '2025-01-21 11:50:26.5242161', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881550091223965696, 1881503648907927552, '查询', '', '', '', '', '', '1', '0', '0', '', 'roleIndex:page', 10109, 3, 1, NULL, 1300000001, '2025-01-21 11:51:13.9159157', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881550170370482176, 1881503648907927552, '新增', '', '', '', '', '', '1', '0', '0', '', 'roleIndex:add', 10119, 3, 1, NULL, 1300000001, '2025-01-21 11:51:32.7855608', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881550231213056000, 1881503648907927552, '编辑', '', '', '', '', '', '1', '0', '0', '', 'roleIndex:edit', 10129, 3, 1, NULL, 1300000001, '2025-01-21 11:51:47.2918905', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881550282572308480, 1881503648907927552, '删除', '', '', '', '', '', '1', '0', '0', '', 'roleIndex:delete', 10139, 3, 1, NULL, 1300000001, '2025-01-21 11:51:59.5364969', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881550362545102848, 1881503648907927552, '数据权限', '', '', '', '', '', '1', '0', '0', '', 'roleIndex:data_type', 10149, 3, 1, NULL, 1300000001, '2025-01-21 11:52:18.6037307', 1300000001, '2025-01-21 19:21:20.1639355', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881662579596730368, 1300000003, '用户管理', 'userIndex', '/system/usermanage', '/system/user/index.vue', 'el-UserFilled', '', '1', '0', '0', '', '', 10159, 2, 1, NULL, 1300000001, '2025-01-21 19:18:13.2327844', 1300000001, '2025-01-30 19:25:37.8737317', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881662811004870656, 1881662579596730368, '查询', '', '', '', '', '', '1', '0', '0', '', 'userIndex:page', 10169, 3, 1, NULL, 1300000001, '2025-01-21 19:19:08.4050965', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881662934095110144, 1881662579596730368, '新增', '', '', '', '', '', '1', '0', '0', '', 'userIndex:add', 10179, 3, 1, NULL, 1300000001, '2025-01-21 19:19:37.7524318', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881662997173248000, 1881662579596730368, '编辑', '', '', '', '', '', '1', '0', '0', '', 'userIndex:edit', 10189, 3, 1, NULL, 1300000001, '2025-01-21 19:19:52.7915142', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881663062772162560, 1881662579596730368, '删除', '', '', '', '', '', '1', '0', '0', '', 'userIndex:delete', 10199, 3, 1, NULL, 1300000001, '2025-01-21 19:20:08.4310281', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881663313054670848, 1881662579596730368, '重置密码', '', '', '', '', '', '1', '0', '0', '', 'userIndex:reset_password', 10209, 3, 1, NULL, 1300000001, '2025-01-21 19:21:08.1029911', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881943420327567360, 1300000003, '职位管理', 'positionIndex', '/system/positionmanage', '/system/position/index.vue', 'el-GoldMedal', '', '1', '0', '0', '', '', 10219, 2, 1, NULL, 1300000001, '2025-01-22 13:54:10.8807082', 1300000001, '2025-01-30 19:26:04.5107975', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881943540813144064, 1881943420327567360, '查询', '', '', '', '', '', '1', '0', '0', '', 'positionIndex:page', 10229, 3, 1, NULL, 1300000001, '2025-01-22 13:54:39.6067668', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881943652230635520, 1881943420327567360, '新增', '', '', '', '', '', '1', '0', '0', '', 'positionIndex:add', 10239, 3, 1, NULL, 1300000001, '2025-01-22 13:55:06.1711463', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881943716881637376, 1881943420327567360, '编辑', '', '', '', '', '', '1', '0', '0', '', 'positionIndex:edit', 10249, 3, 1, NULL, 1300000001, '2025-01-22 13:55:21.5858833', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1881943791406030848, 1881943420327567360, '删除', '', '', '', '', '', '1', '0', '0', '', 'positionIndex:delete', 10259, 3, 1, NULL, 1300000001, '2025-01-22 13:55:39.3533765', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882349224964792320, 1883382946094784512, '租户管理', 'tenantIndex', '/platform/tenantmanage', '/system/tenant/index.vue', 'fa-building', '', '1', '0', '0', '', '', 10269, 2, 1, NULL, 1300000001, '2025-01-23 16:46:42.2464421', 1300000001, '2025-01-30 19:28:13.142124', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882349376454664192, 1882349224964792320, '查询', '', '', '', '', '', '1', '0', '0', '', 'tenantIndex:page', 10279, 3, 1, NULL, 1300000001, '2025-01-23 16:47:18.3645334', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882349465847865344, 1882349224964792320, '新增', '', '', '', '', '', '1', '0', '0', '', 'tenantIndex:add', 10289, 3, 1, NULL, 1300000001, '2025-01-23 16:47:39.6768931', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882349519795003392, 1882349224964792320, '删除', '', '', '', '', '', '1', '0', '0', '', 'tenantIndex:delete', 10299, 3, 1, NULL, 1300000001, '2025-01-23 16:47:52.5390664', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882349714918219776, 1882349224964792320, '启/禁用', '', '', '', '', '', '1', '0', '0', '', 'tenantIndex:open_close', 10309, 3, 1, NULL, 1300000001, '2025-01-23 16:48:39.0604536', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882586556456378368, 1883382946094784512, '数据字典', 'dataDictIndex', '/platform/datadictmanage', '/system/dataDict/index.vue', 'el-Files', '', '1', '0', '0', '', '', 10319, 2, 1, NULL, 1300000001, '2025-01-24 08:29:46.4833116', 1300000001, '2025-01-30 19:28:30.2912673', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882586772391731200, 1882586556456378368, '查询', '', '', '', '', '', '1', '0', '0', '', 'dataDictIndex:page', 10329, 3, 1, NULL, 1300000001, '2025-01-24 08:30:37.966009', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882586909759381504, 1882586556456378368, '新增', '', '', '', '', '', '1', '0', '0', '', 'dataDictIndex:add', 10339, 3, 1, NULL, 1300000001, '2025-01-24 08:31:10.7175733', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882586978227200000, 1882586556456378368, '编辑', '', '', '', '', '', '1', '0', '0', '', 'dataDictIndex:edit', 10349, 3, 1, NULL, 1300000001, '2025-01-24 08:31:27.0412233', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882587059437314048, 1882586556456378368, '编辑字典', '', '', '', '', '', '1', '0', '0', '', 'dataDictIndex:edit_dict', 10359, 3, 1, NULL, 1300000001, '2025-01-24 08:31:46.4034167', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1882587136541204480, 1882586556456378368, '删除', '', '', '', '', '', '1', '0', '0', '', 'dataDictIndex:delete', 10369, 3, 1, NULL, 1300000001, '2025-01-24 08:32:04.7865239', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883382946094784512, 0, '平台管理', 'platform', '/platform', 'Layout', 'el-Grid', '', '1', '0', '0', '', '', 10379, 1, 1, NULL, 1300000001, '2025-01-26 13:14:20.5693886', 1300000001, '2025-01-26 13:14:48.4761318', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883383621906210816, 1883382946094784512, 'Job管理', 'autoJobIndex', '/platform/autojobmanage', '/system/autoJob/index.vue', 'el-AlarmClock', '', '1', '0', '0', '', '', 10389, 2, 1, NULL, 1300000001, '2025-01-26 13:17:01.6950007', 1300000001, '2025-01-30 19:28:38.0339324', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883383816484167680, 1883383621906210816, '查询', '', '', '', '', '', '1', '0', '0', '', 'autoJobIndex:page', 10399, 3, 1, NULL, 1300000001, '2025-01-26 13:17:48.0861483', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883383938383224832, 1883383621906210816, '启用/暂停', '', '', '', '', '', '1', '0', '0', '', 'autoJobIndex:start_stop', 10409, 3, 1, NULL, 1300000001, '2025-01-26 13:18:17.1496513', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883384080838565888, 1883383621906210816, '延期', '', '', '', '', '', '1', '0', '0', '', 'autoJobIndex:deferred', 10419, 3, 1, NULL, 1300000001, '2025-01-26 13:18:51.1134849', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883488734456979456, 1883382946094784512, '登录日志', 'logLoginIndex', '/platform/logLogin', '/system/log/logLoginIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10429, 2, 1, NULL, 1300000001, '2025-01-26 20:14:42.480569', 1300000001, '2025-01-30 19:28:51.5467134', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883488963273039872, 1883488734456979456, '查询', '', '', '', '', '', '1', '0', '0', '', 'logLoginIndex:page', 10439, 3, 1, NULL, 1300000001, '2025-01-26 20:15:37.0342829', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883493046981632000, 1883382946094784512, 'Job日志', 'logJobIndex', '/platform/logJob', '/system/log/logJobIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10449, 2, 1, NULL, 1300000001, '2025-01-26 20:31:50.6662371', 1300000001, '2025-01-30 19:29:00.4065826', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883493141546409984, 1883493046981632000, '查询', '', '', '', '', '', '1', '0', '0', '', 'logJobIndex:page', 10459, 3, 1, NULL, 1300000001, '2025-01-26 20:32:13.2119815', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883499334012641280, 1883382946094784512, '事件日志', 'logEventIndex', '/platform/logevent', '/system/log/logEventIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10469, 2, 1, NULL, 1300000001, '2025-01-26 20:56:49.6114059', 1300000001, '2025-01-30 19:29:10.3446137', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883499428980072448, 1883499334012641280, '查询', '', '', '', '', '', '1', '0', '0', '', 'logEventIndex:page', 10479, 3, 1, NULL, 1300000001, '2025-01-26 20:57:12.2535472', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883502055633592320, 1883382946094784512, '差异日志', 'logDiffIndex', '/platform/logDiff', '/system/log/logDiffIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10489, 2, 1, NULL, 1300000001, '2025-01-26 21:07:38.49629', 1300000001, '2025-01-30 19:29:16.9988189', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883502134012551168, 1883502055633592320, '查询', '', '', '', '', '', '1', '0', '0', '', 'logDiffIndex:page', 10499, 3, 1, NULL, 1300000001, '2025-01-26 21:07:57.1829096', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883505043135668224, 1883382946094784512, '操作日志', 'logOperateIndex', '/platform/logOperate', '/system/log/logOperateIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10509, 2, 1, NULL, 1300000001, '2025-01-26 21:19:30.7723921', 1300000001, '2025-01-30 19:29:23.9668611', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883505240246984704, 1883382946094784512, '异常日志', 'logExceptionIndex', '/platform/logException', '/system/log/logExceptionIndex.vue', 'el-Document', '', '1', '0', '0', '', '', 10519, 2, 1, NULL, 1300000001, '2025-01-26 21:20:17.766827', 1300000001, '2025-01-30 19:29:30.5989651', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883505350582345728, 1883505043135668224, '查询', '', '', '', '', '', '1', '0', '0', '', 'logOperateIndex:page', 10529, 3, 1, NULL, 1300000001, '2025-01-26 21:20:44.0733588', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1883505428315381760, 1883505240246984704, '查询', '', '', '', '', '', '1', '0', '0', '', 'logExceptionIndex:page', 10539, 3, 1, NULL, 1300000001, '2025-01-26 21:21:02.60669', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884778107420942336, 1300000003, '个人中心', 'personalCenterIndex', '/system/personalcenter', '/system/personalCenter/index.vue', 'fa-street-view', '', '1', '0', '0', '', '', 10549, 2, 1, NULL, 1300000001, '2025-01-30 09:38:12.9499722', 1300000001, '2025-01-30 19:26:41.1378333', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884778243870040064, 1884778107420942336, '查询', '', '', '', '', '', '1', '0', '0', '', 'personalCenterIndex:view', 10559, 3, 1, NULL, 1300000001, '2025-01-30 09:38:45.4820811', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884857795430457344, 1881662579596730368, '导出', '', '', '', '', '', '1', '0', '0', '', 'userIndex:export', 10569, 3, 1, NULL, 1300000001, '2025-01-30 14:54:52.0518358', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1884857884613943296, 1881662579596730368, '导入', '', '', '', '', '', '1', '0', '0', '', 'userIndex:import', 10579, 3, 1, NULL, 1300000001, '2025-01-30 14:55:13.3147822', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886302722643337216, 1300000003, '通知公告', 'publishmessage', '/system/publishmessage', '/system/message/publishIndex.vue', 'fa-desktop', '', '1', '0', '0', '', '', 10589, 2, 1, NULL, 1300000001, '2025-02-03 14:36:29.5449834', 1300000001, '2025-02-03 14:47:59.5327487', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886305270632685568, 1300000001, '站内信', 'receivemessage', '/system/receivemessage', '/system/message/receiveIndex.vue', 'fa-envelope-o', '', '1', '0', '0', '', '', 10599, 2, 1, NULL, 1300000001, '2025-02-03 14:46:37.0335095', 1300000001, '2025-02-03 14:47:18.9547777', 1300000001, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886305880748728320, 1886302722643337216, '查询', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:page', 10609, 3, 1, NULL, 1300000001, '2025-02-03 14:49:02.4964854', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886305957932310528, 1886302722643337216, '新增', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:add', 10619, 3, 1, NULL, 1300000001, '2025-02-03 14:49:20.8983917', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886306037544394752, 1886302722643337216, '编辑', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:edit', 10629, 3, 1, NULL, 1300000001, '2025-02-03 14:49:39.8793455', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886306151197450240, 1886302722643337216, '删除', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:delete', 10639, 3, 1, NULL, 1300000001, '2025-02-03 14:50:06.976169', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886369812943347712, 1886302722643337216, '发布', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:publish', 10649, 3, 1, NULL, 1300000001, '2025-02-03 19:03:05.1189767', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886587042893275136, 1300000002, '查询', '', '', '', '', '', '1', '0', '0', '', 'dashboardIndex:page', 10659, 3, 1, NULL, 1300000001, '2025-02-04 09:26:16.7743615', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886587128931033088, 1886305270632685568, '查询', '', '', '', '', '', '1', '0', '0', '', 'receivemessage:page', 10669, 3, 1, NULL, 1300000001, '2025-02-04 09:26:37.2878619', 1300000001, NULL, NULL, '0');
INSERT INTO "SysMenu" ("Id", "ParentId", "MenuName", "RouteName", "RoutePath", "ComponentPath", "MenuIcon", "RedirectPath", "IsCache", "OpenNewWindow", "IsAffix", "OutLink", "Permission", "Sort", "MenuType", "Status", "Remark", "CreateOrgId", "CreateTime", "CreateUserId", "UpdateTime", "UpdateUserId", "IsDelete") VALUES (1886613824367370240, 1886302722643337216, '撤回', '', '', '', '', '', '1', '0', '0', '', 'publishIndex:recalled', 10679, 3, 1, NULL, 1300000001, '2025-02-04 11:12:41.9759527', 1300000001, NULL, NULL, '0');

63
API/Wood.Admin.WebApi/Filter/ApiAuthorizeAttribute.cs

@ -0,0 +1,63 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using System;
using Wood.Util.JwtAuthorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using System.Threading.Tasks;
using Wood.Cache;
using Wood.Entity.SystemManage;
using System.Linq;
using Wood.Data.Repository;
using Wood.Util;
using Wood.Service.SystemManage.Manager;
using Microsoft.AspNetCore.Identity;
using Wood.Entity;
namespace Wood.Admin.WebApi.Filter
{
public class ApiAuthorizeFilter : IAsyncAuthorizationFilter
{
private readonly ICache _cache;
private readonly UserManager _userManager;
public ApiAuthorizeFilter(ICache cache, UserManager userManager)
{
_cache = cache;
_userManager = userManager;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
//控制器允许匿名访问
if (context.ActionDescriptor.EndpointMetadata.Any(it => it.GetType() == typeof(AllowAnonymousAttribute)))
return;
//实现自定义的验证逻辑
//有权限时不要设置 context.Result
//错误
//context.Result = new BadRequestResult();
//用户信息
var userInfo = context.HttpContext.UserInfo();
//用户信息不为空 而且 存在用户的缓存信息 表示用户登录中
//否则需要重新登录
if (userInfo != null && userInfo.UserId > 0)
{
//判断用户缓存是否存在
if (_cache.GetCache<UserCache>(userInfo.CacheKey) != null)
return;
else
{
//缓存不存在 从数据库中重新加载用户信息
await _userManager.InitCache(userInfo.UserId, DateTime.Now.AddMinutes(GlobalContext.JwtConfig!.TokenExpire));
return;
}
}
//未授权
context.Result = new UnauthorizedResult();
return;
}
}
}

34
API/Wood.Admin.WebApi/Filter/ApiExceptionFilter.cs

@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
using Wood.Entity;
namespace Wood.Admin.WebApi.Filter
{
/// <summary>
/// action 异常捕捉 filter
/// </summary>
public class ApiExceptionFilter : IAsyncExceptionFilter
{
/// <summary>
/// 异常捕捉 返回
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task OnExceptionAsync(ExceptionContext context)
{
// 设置统一的响应格式
context.Result = new JsonResult(TData.Error(context.Exception.Message))
{
StatusCode = StatusCodes.Status200OK
};
// 标记异常已处理
context.ExceptionHandled = true;
await Task.CompletedTask;
}
}
}

135
API/Wood.Admin.WebApi/Filter/ApiPerformanceLoggingFilter.cs

@ -0,0 +1,135 @@
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using SqlSugar.Extensions;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Wood.Entity;
using Wood.Entity.SystemManage;
using Wood.EventBus;
using Wood.EventBus.Events;
using Wood.Util;
using Wood.Util.JwtAuthorization;
namespace Wood.Admin.WebApi.Filter
{
/// <summary>
/// 性能统计
/// </summary>
public class ApiPerformanceLoggingFilter : ActionFilterAttribute
{
private readonly IEventBus _eventBus;
/// <summary>
///
/// </summary>
/// <param name="eventBus"></param>
public ApiPerformanceLoggingFilter(IEventBus eventBus)
{
_eventBus = eventBus;
}
/// <summary>
/// 异步接口日志
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
Stopwatch sw = new Stopwatch();
if (context.ModelState.IsValid)
{
sw.Start();
var resultContext = await next();
sw.Stop();
var user = context.HttpContext.UserInfo();
#region 保存日志
LogOperationEntity logOperationEntity = new LogOperationEntity();
logOperationEntity.RequestUrl = context.HttpContext.Request.Path;
logOperationEntity.Elapsed = (int)sw.ElapsedMilliseconds;
logOperationEntity.Browser = NetHelper.Browser;
logOperationEntity.Os = NetHelper.GetOSVersion();
logOperationEntity.LogDateTime = DateTime.Now;
logOperationEntity.CreateTime = DateTime.Now;
logOperationEntity.CreateUserId = user?.UserId;
logOperationEntity.UserName = user?.UserName;
logOperationEntity.RealName = user?.RealName;
logOperationEntity.HttpMethod = context.HttpContext.Request.Method.ToUpper();
logOperationEntity.IpAddress = NetHelper.Ip;
logOperationEntity.ControllerName = context.Controller.GetType().Name;
logOperationEntity.ActionName = context.RouteData.Values["action"]?.ToString();
logOperationEntity.MethodName = context.ActionDescriptor.DisplayName;
#region 获取Post参数
switch (logOperationEntity.HttpMethod)
{
case "GET":
logOperationEntity.RequestParam = context.HttpContext.Request.QueryString.Value;
break;
case "POST":
default:
if (context.ActionArguments?.Count > 0)
{
logOperationEntity.RequestUrl += context.HttpContext.Request.QueryString.Value;
logOperationEntity.RequestParam = JsonConvert.SerializeObject(context.ActionArguments);
}
else
logOperationEntity.RequestParam = context.HttpContext.Request.QueryString.Value;
break;
}
#endregion
if (resultContext.Exception != null)
{
var logExceptionEntity = logOperationEntity.Adapt<LogExceptionEntity>();
logExceptionEntity.ReturnResult = resultContext.Exception.GetFullExceptionMessage();
logExceptionEntity.Exception = resultContext.Exception.GetFullExceptionMessage();
logExceptionEntity.ExceptionStackTrace = resultContext.Exception.StackTrace;
logExceptionEntity.Source = this.GetType().Name;
_eventBus.Publish(new LogExceptionEvent(logExceptionEntity));
}
else
{
ObjectResult? result = resultContext.Result as ObjectResult;
if (result != null)
logOperationEntity.ReturnResult = JsonConvert.SerializeObject(result.Value);
}
_eventBus.Publish(new LogOperationEvent() { Payload = logOperationEntity });
#endregion
}
else
{
var errors = string.Join("; ", context.ModelState.GetAllErrorMessages());
var user = context.HttpContext.UserInfo();
LogOperationEntity logOperationEntity = new LogOperationEntity();
logOperationEntity.RequestUrl = context.HttpContext.Request.Path;
logOperationEntity.Elapsed = (int)sw.ElapsedMilliseconds;
logOperationEntity.Browser = NetHelper.Browser;
logOperationEntity.Os = NetHelper.GetOSVersion();
logOperationEntity.LogDateTime = DateTime.Now;
logOperationEntity.CreateTime = DateTime.Now;
logOperationEntity.CreateUserId = user?.UserId;
logOperationEntity.UserName = user?.UserName;
logOperationEntity.RealName = user?.RealName;
logOperationEntity.HttpMethod = context.HttpContext.Request.Method.ToUpper();
logOperationEntity.IpAddress = NetHelper.Ip;
logOperationEntity.ControllerName = context.Controller.GetType().Name;
logOperationEntity.ActionName = context.RouteData.Values["action"]?.ToString();
logOperationEntity.MethodName = context.ActionDescriptor.DisplayName;
logOperationEntity.Message = "ModelStateError";
logOperationEntity.ReturnResult = errors;
_eventBus.Publish(new LogOperationEvent() { Payload = logOperationEntity });
context.Result = new ObjectResult(TData.Error(errors));
}
}
}
}

117
API/Wood.Admin.WebApi/Filter/ApiResponseWrapperFilter.cs

@ -0,0 +1,117 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Wood.Entity;
using System.Net;
using Azure;
namespace Wood.Admin.WebApi.Filter
{
/// <summary>
/// action结果包装filter
/// </summary>
public class ApiResponseWrapperFilter : IAsyncResultFilter
{
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
//检查当前结果是否是 ObjectResult
if (context.Result is ObjectResult objectResult && objectResult.Value != null)
{
if (objectResult.Value is TData)
{
await next();
return;
}
var wrappedResponse = TData.Success<object>();
wrappedResponse.Data = objectResult.Value;
// 修改响应内容
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = (int)HttpStatusCode.OK
};
}
else if (context.Result is EmptyResult)
{
var wrappedResponse = TData.Success<object>();
// 修改响应内容
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = (int)HttpStatusCode.OK
};
}
else if (context.Result is StatusCodeResult statusCodeResult)
{
// 处理非成功的状态码
var wrappedResponse = new TData
{
Code = 0,
Message = $"Error with status code: {statusCodeResult.StatusCode}"
};
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = statusCodeResult.StatusCode
};
}
else if (context.Result is BadRequestObjectResult badRequestResult)
{
// 处理 Bad Request
var wrappedResponse = new TData<object>
{
Code = 0,
Data = badRequestResult.Value,
Message = "Bad request"
};
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = badRequestResult.StatusCode
};
}
else if (context.Result is NotFoundResult notFoundResult)
{
// 处理 Not Found
var wrappedResponse = new TData
{
Code = 0,
Message = "Resource not found"
};
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = StatusCodes.Status404NotFound
};
}
else if (context.Result is UnauthorizedResult unauthorizedResult)
{
// 处理 Unauthorized
var wrappedResponse = new TData
{
Code = 0,
Message = "Unauthorized access"
};
context.Result = new JsonResult(wrappedResponse)
{
StatusCode = StatusCodes.Status401Unauthorized
};
}
else if (context.Result is FileStreamResult || context.Result is FileResult)
{
//设置头部 否则前端接受不到文件名称
context.HttpContext.Response.Headers?.Append("Access-Control-Expose-Headers", "Content-Disposition");
}
// next 必须放在后边
await next();
}
}
}

33
API/Wood.Admin.WebApi/Middleware/FileServerMiddleware.cs

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Http;
using System.Net;
using System.Threading.Tasks;
namespace Wood.Admin.WebApi.Middleware
{
public class FileBridgeMiddleware
{
private readonly RequestDelegate _next;
public FileBridgeMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.ToString().Contains("fromBucket/xxx(仓储名字)"))
{
//拦截到仓储文件的路径 读取文件返回
byte[] filebytes = new byte[0];
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.Body.WriteAsync(filebytes);
await context.Response.Body.FlushAsync();
}
else
{
// Call the next delegate/middleware in the pipeline.
await _next(context);
}
}
}
}

81
API/Wood.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs

@ -0,0 +1,81 @@
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Net;
using System.Threading.Tasks;
using Wood.Entity;
using Wood.EventBus;
using Wood.EventBus.Events;
using Wood.Util;
namespace Wood.Admin.WebApi.Middleware
{
/// <summary>
/// 全局异常中间件
/// </summary>
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly IEventBus _eventBus;
/// <summary>
/// 全局异常中间件
/// </summary>
/// <param name="next"></param>
/// <param name="eventBus"></param>
public GlobalExceptionMiddleware(RequestDelegate next, IEventBus eventBus)
{
_next = next;
_eventBus = eventBus;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context /* other dependencies */)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="exception"></param>
/// <returns></returns>
private Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var user = GlobalContext.UserInfo;
var entity = new Entity.SystemManage.LogExceptionEntity
{
UserName = user?.UserName,
RealName = user?.RealName,
HttpMethod = context.Request.Method.ToUpper(),
Browser = NetHelper.Browser,
Os = NetHelper.GetOSVersion(),
Exception = exception.GetFullExceptionMessage(),
ExceptionStackTrace = exception.StackTrace,
Elapsed = 0,
LogDateTime = DateTime.Now,
IpAddress = NetHelper.Ip,
Source = this.GetType().Name,
};
entity.RequestUrl = context.Request.Path;
entity.RequestParam = context.Request.QueryString.Value;
_eventBus.Publish(new LogExceptionEvent(entity));
var code = HttpStatusCode.OK;
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return context.Response.WriteAsync(JsonConvert.SerializeObject(TData.Error()));
}
}
}

25
API/Wood.Admin.WebApi/Middleware/ModelBindingMetadataProvider.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
namespace Wood.Admin.WebApi.Middleware
{
/// <summary>
/// Controller Model Binding 处理
/// </summary>
public class ModelBindingMetadataProvider : IMetadataDetailsProvider, IDisplayMetadataProvider
{
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
if (context.Key.MetadataKind == ModelMetadataKind.Property)
{
context.DisplayMetadata.ConvertEmptyStringToNull = false;
}
}
}
}

127
API/Wood.Admin.WebApi/Other/AutoRouteConvention.cs

@ -0,0 +1,127 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing.Template;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wood.Util;
namespace Wood.Admin.WebApi
{
/// <summary>
/// 自动扫描所有带service名称的程序集
/// 扫描程序集中所有带service后缀的类
/// 给类中所有public 方法注册路由
/// </summary>
public class AutoRouteConvention : IApplicationModelConvention
{
private readonly string _baseRoutePrefix = "api";
/// <summary>
/// 应用路由规则
/// get 开头为 get
/// 其他为post
/// </summary>
/// <param name="application"></param>
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
var controllerName = controller.ControllerName.ToLowerInvariant().Replace("service", "");
foreach (var action in controller.Actions)
{
var actionName = action.ActionName.ToLowerInvariant();
var httpMethod = "POST";
var isGetMethod = false;
if (!action.Selectors.Any() || !action.Selectors[0].ActionConstraints.Any())
{
if (actionName.StartsWith("get"))
{
httpMethod = "GET";
actionName = actionName.Substring(3);
isGetMethod = true;
}
else if (actionName.StartsWith("post"))
{
httpMethod = "POST";
actionName = actionName.Substring(4);
}
// 构建路由模板
var routeTemplate = $"{_baseRoutePrefix}/{controllerName}/{actionName}";
if (action.Selectors.Any())
{
//当前已经有了 Selectors 信息则直接设置
action.Selectors[0].AttributeRouteModel = new AttributeRouteModel { Template = routeTemplate };
action.Selectors[0].ActionConstraints.Add(new HttpMethodActionConstraint(new[] { httpMethod }));
}
else
{
//当前没有 Selectors 信息则直接新增
var selectorModel = new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel { Template = routeTemplate },
};
selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { httpMethod }));
action.Selectors.Add(selectorModel);
}
}
else
{
// 构建路由模板
var routeTemplate = $"{_baseRoutePrefix}/{controllerName}/{actionName}";
//重新指定路由路径
action.Selectors[0].AttributeRouteModel = new AttributeRouteModel { Template = routeTemplate };
//是否get请求
isGetMethod = action.Attributes.Any(it => it.GetType() == typeof(HttpGetAttribute));
}
//查找所有没有绑定来源的参数
IEnumerable<ParameterModel> noBindModels = action.Parameters.Where(it => it.BindingInfo == null);
if (noBindModels.Any())
{
// 设置参数来源:GET 请求的参数来自 URL,POST 请求的参数来自请求体
// 只会设置没有明确指定来源的参数
// Get 会加上 FromQuery
// Post 会加上 FromBody (只有第一个参数加上 Frombody 多个参数会报错!)
if (isGetMethod)
{
foreach (var parameter in noBindModels)
{
var bindId = parameter.BindingInfo?.BindingSource?.Id;
if (string.IsNullOrEmpty(bindId))
{
// 对于 GET 请求,默认情况下参数应该来自于查询字符串或路径
parameter.BindingInfo = new BindingInfo() { BindingSource = BindingSource.Query };
// 对于 GET 请求,默认情况下参数应该来自于 URL
//parameter.BindingInfo = new BindingInfo() { BindingSource = BindingSource.Path };
}
}
}
else
{
if (noBindModels.Count() > 1)
throw Oops.Oh($"系统不支持Post请求FromBody绑定多个参数,请改成一个。路径:Controller({controller.ControllerName})Action({action.ActionName})");
else
{
if (action.Parameters.Any(it => it.BindingInfo?.BindingSource?.Id == "Body"))
throw Oops.Oh($"系统不支持Post请求FromBody绑定多个参数,请改成一个。路径:Controller({controller.ControllerName})Action({action.ActionName})");
noBindModels.First().BindingInfo = new BindingInfo() { BindingSource = BindingSource.Body };
}
}
}
}
}
}
}
}

214
API/Wood.Admin.WebApi/Other/ServiceCollectionExtensions.cs

@ -0,0 +1,214 @@
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using SqlSugar;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Wood.AutoJob;
using Wood.Cache;
using Wood.Data.Repository;
using Wood.Entity;
using Wood.EventBus;
using Wood.MemoryCache;
using Wood.RedisCache;
using Wood.Util;
namespace Wood.Admin.WebApi
{
/// <summary>
/// 服务拓展
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 扫描指定程序集中的所有类型,并根据其实现的生命周期接口自动注册到DI容器中。
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="assemblies">要扫描的程序集数组</param>
public static void ScanAndRegisterLifeTimes(this IServiceCollection services, params Assembly[] assemblies)
{
var lifeTimeServices = typeof(ILifeTimeService);
foreach (var assembly in assemblies)
{
// 获取实现了 ILifeTimeService 的非抽象类
var types = assembly.GetTypes()
.Where(t => !t.IsAbstract && t.IsClass && lifeTimeServices.IsAssignableFrom(t));
foreach (var type in types)
{
// 查找实现了哪些生命周期接口
var lifeTimeInterfaces = type.GetInterfaces()
.Where(i => i != lifeTimeServices && lifeTimeServices.IsAssignableFrom(i))
.ToList();
if (!lifeTimeInterfaces.Any())
{
continue; // 如果没有实现任何生命周期接口,则跳过此类型
}
// 根据第一个匹配的生命周期接口注册服务
var lifeTimeInterface = lifeTimeInterfaces.First();
if (typeof(ITransient).IsAssignableFrom(lifeTimeInterface))
{
services.AddTransient(type, type);
}
else if (typeof(IScoped).IsAssignableFrom(lifeTimeInterface))
{
services.AddScoped(type, type);
}
else if (typeof(ISingleton).IsAssignableFrom(lifeTimeInterface))
{
services.AddSingleton(type, type);
}
}
}
}
#region eventbus 初始化
public static IServiceCollection AddEventBus(this IServiceCollection services)
{
services.AddSingleton<IEventBus, InMemoryEventBus>();
return services;
}
/// <summary>
/// 自动注册所有订阅事件
/// </summary>
/// <param name="serviceProvider"></param>
public static void UseEventBus(this IApplicationBuilder app, Assembly[] assemblies)
{
var eventBus = GlobalContext.ServiceProvider!.GetRequiredService<IEventBus>();
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract)
.SelectMany(t => t.GetInterfaces(), (t, i) => new { Type = t, Interface = i })
.Where(x => x.Interface.IsGenericType && x.Interface.GetGenericTypeDefinition() == typeof(IIntegrationEventHandler<>));
foreach (var type in types)
{
var eventType = type.Interface.GetGenericArguments()[0];
var handlerType = type.Type;
var handlerInstance = (dynamic)GlobalContext.ServiceProvider!.GetService(handlerType)!;
var eventName = eventType.Name;
var subscribeMethod = typeof(InMemoryEventBus).GetMethod("Subscribe")!.MakeGenericMethod(eventType, handlerType);
subscribeMethod.Invoke(eventBus, new object[] { handlerInstance });
}
}
}
#endregion
#region autoJob 初始化
public static void UseAutoJob(this IApplicationBuilder app)
{
Task.Run(async () =>
{
if (GlobalContext.SystemConfig!.RunAutoJob)
{
//延迟 5s
await Task.Delay(5 * 1000);
try
{
AutoJobCenter jobCenter = new AutoJobCenter();
jobCenter.ScanJob();
await jobCenter.AddScheduleJob();
}
catch (Exception ex)
{
Log.Error(ex, "初始化自动job失败!");
}
}
});
}
#endregion
#region sqlsugar初始化
// <summary>
/// SqlSugar 上下文初始化
/// </summary>
/// <param name="services"></param>
public static void AddSqlSugar(this IServiceCollection services, IConfiguration configuration)
{
// 自定义 SqlSugar 雪花ID算法
SnowFlakeSingle.WorkId = GlobalContext.SystemConfig!.SnowFlakeWorkerId;
if (Enum.TryParse(GlobalContext.SystemConfig.DBProvider, true, out SqlSugar.DbType dbType))
{
services.AddSingleton<ISqlSugarClient>(s =>
{
SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
{
ConnectionString = GlobalContext.SystemConfig.DBConnectionString,
DbType = dbType,
IsAutoCloseConnection = true
}, db =>
{
SqlSugarDbContext.SetDbDiffLog(db.Context);
SqlSugarDbContext.SetDbAop(db.Context);
});
return sqlSugar;
}); // 单例注册
services.AddScoped(typeof(SqlSugarRepository<>)); // 仓储注册
services.AddTransient<IUnitOfWork, SqlSugarUnitOfWork>(); // 事务与工作单元注册
}
else
throw Oops.Oh("不支持的数据库类型!");
}
/// <summary>
/// 初始化数据库
/// </summary>
/// <param name="app"></param>
public static void UseSqlSugar(this IApplicationBuilder app)
{
var sqlsugar = GlobalContext.ServiceProvider!.GetService<ISqlSugarClient>();
// 初始化数据库表结构及种子数据
SqlSugarDbContext.InitDatabase(sqlsugar!);
}
#endregion
/// <summary>
/// 开启缓存
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddCache(this IServiceCollection services)
{
switch (GlobalContext.SystemConfig!.CacheProvider)
{
case "Redis": services.AddSingleton<ICache, RedisCacheImp>(); break;
default:
case "Memory": services.AddSingleton<ICache, MemoryCacheImp>(); break;
}
;
return services;
}
/// <summary>
/// Magicodes
/// 导入导出
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddMagicodesIE(this IServiceCollection services)
{
// 注册 Excel 导出器
services.AddSingleton<IExcelExporter, ExcelExporter>();
services.AddSingleton<IExcelImporter, ExcelImporter>();
// 如果需要支持其他格式(如 PDF、Word 等),可以在这里添加相应的导出器
// services.AddSingleton<IExporter, PdfExporter>();
// services.AddSingleton<IExporter, WordExporter>();
return services;
}
}
}

61
API/Wood.Admin.WebApi/Program.cs

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
namespace Wood.Admin.WebApi
{
/// <summary>
/// program
/// </summary>
public class Program
{
/// <summary>
/// main
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
// 创建并配置Serilog Logger
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information() // 设置最低日志级别
.Enrich.FromLogContext() // 增加上下文信息
.WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}{Exception}") // 输出到控制台模板
.WriteTo.File("logs\\log.txt",
rollingInterval: RollingInterval.Day,// 按天分割,每天滚动创建新的日志文件
retainedFileCountLimit: 90,// 只保存最近90天的日志
fileSizeLimitBytes: 10_485_760, // 文件大小限制为10MB (10 * 1024 * 1024 bytes)
rollOnFileSizeLimit: true, // 达到文件大小限制时滚动
outputTemplate: "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff} LogLevel:{Level}{NewLine}{Message}{NewLine}" + new string('-', 50) + "{NewLine}"// 模板
)
.CreateLogger();
try
{
// 创建Host
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
/// <summary>
/// 启用
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // 使用Serilog作为日志提供者
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

22
API/Wood.Admin.WebApi/Properties/launchSettings.json

@ -0,0 +1,22 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:7001",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"Wood.Admin.WebApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api-doc",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:7001"
}
}
}

346
API/Wood.Admin.WebApi/Startup.cs

@ -0,0 +1,346 @@
using Hangfire;
using Hangfire.SqlServer;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Quartz;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using TaskManager.Controllers;
using TaskManager.EntityFramework;
using Wood.Admin.WebApi.Filter;
using Wood.Admin.WebApi.Middleware;
using Wood.Util;
namespace Wood.Admin.WebApi
{
/// <summary>
/// 入口
/// </summary>
public class Startup
{
/// <summary>
/// 配置
/// </summary>
public IConfiguration Configuration { get; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="configuration"></param>
/// <param name="env"></param>
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
GlobalContext.LogWhenStart(env);
GlobalContext.HostingEnvironment = env;
}
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
//初始化配置
GlobalContext.SystemConfig = Configuration.GetSection("SystemConfig").Get<SystemConfig>()!;
GlobalContext.JwtConfig = Configuration.GetSection("JwtConfig").Get<JwtConfig>()!;
GlobalContext.Services = services;
GlobalContext.Configuration = Configuration;
//初始化 eventbus
services.AddEventBus();
//初始化数据库
services.AddSqlSugar(Configuration);
services.AddHttpClient();
services.AddTransient<LogController>();
services.AddTransient<SupplierProPlaningService>();
services.AddTransient<TaskConifgureController>();
// 配置 DbContext 使用 SQL Server 连接字符串
services.AddDbContext<JobDbContext>(options =>
options.UseSqlServer(GlobalContext.SystemConfig.CustomerDb));
// 配置 Hangfire 使用 SQL Server 存储
services.AddHangfire(
configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170) // 建议显式设置兼容性版本
.UseSimpleAssemblyNameTypeSerializer() // 简化类型序列化(可选)
.UseRecommendedSerializerSettings() // 使用推荐的序列化设置(可选)
.UseSqlServerStorage(GlobalContext.SystemConfig.CustomerDb, new SqlServerStorageOptions
{
// 可从配置中读取 Hangfire 存储选项(如队列、重试策略等)
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
})
//.UseFilter(services.BuildServiceProvider().GetRequiredService<ILogger<LogJobFilter>>())
); // 添加日志过滤器(可选)
services.AddHangfireServer(options =>
{
options.WorkerCount = 10;
// 可选:配置队列优先级
//options.Queues = builder.Configuration.GetSection("Hangfire:ServerOptions:Queues").Get<string[]>() ?? new[] { "default" };
});
//注册控制器
services.AddControllers(options =>
{
//自动扫描注册控制器
options.Conventions.Add(new AutoRouteConvention());
//options.ModelMetadataDetailsProviders.Add(new ModelBindingMetadataProvider());
// 添加全局授权过滤器
options.Filters.Add(typeof(ApiAuthorizeFilter));
//options.Filters.Add(typeof(AuthorizeFilter));
//异常处理
options.Filters.Add(typeof(ApiExceptionFilter));
//性能记录,日志记录
options.Filters.Add(typeof(ApiPerformanceLoggingFilter));
//结果包装
options.Filters.Add(typeof(ApiResponseWrapperFilter));
})
.AddNewtonsoftJson(options =>
{
// Json序列化设置
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用
//options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //对象属性名大写
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 对象属性名小写
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; // 忽略空值
options.SerializerSettings.Converters.Add(new LongToStringJsonConverter()); // long转string(防止js精度溢出) 超过16位开启
options.SerializerSettings.Converters.Add(new NullableLongToStringJsonConverter()); // long转string(防止js精度溢出) 超过16位开启
//options.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore; // 解决DateTimeOffset异常
//options.SerializerSettings.DateParseHandling = DateParseHandling.None; // 解决DateTimeOffset异常
//options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal }); // 解决DateTimeOffset异常
});
//添加跨域
services.AddCors();
//添加缓存支持
services.AddMemoryCache();
//初始化缓存
services.AddCache();
//添加 Magicodes.IE 导入导出支持
services.AddMagicodesIE();
//services.AddOptions();
//数据保护服务用于加密敏感数据,如身份验证 cookie 和抗请求伪造令牌。
//默认情况下,数据保护密钥存储在临时目录中,这可能导致在重启后丢失密钥,从而导致用户会话失效等问题
//通过 PersistKeysToFileSystem 方法,可以将密钥存储在一个指定的目录中,确保密钥在应用程序重启后仍然可用
//services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(GlobalContext.HostingEnvironment.ContentRootPath + Path.DirectorySeparatorChar + "DataProtection"));
//默认情况下,.NET Core 不包含所有旧版 Windows 编码(如 GBK、GB2312 等),这些编码通常在处理某些旧系统或特定文件格式时需要。
//通过注册 CodePagesEncodingProvider,可以启用这些额外的编码支持
//Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // 注册Encoding
//注册jwt验证服务
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true, //是否验证Issuer
ValidIssuer = Configuration["JwtConfig:Issuer"], //发行人Issuer
ValidateAudience = true, //是否验证Audience
ValidAudience = Configuration["JwtConfig:Audience"], //订阅人Audience
ValidateIssuerSigningKey = true, //是否验证SecurityKey
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtConfig:SecretKey"]!)), //SecurityKey
ValidateLifetime = true, //是否验证失效时间
ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
RequireExpirationTime = true,
};
});
//身份验证
services.AddAuthorization();
// 添加 Quartz 服务
services.AddQuartz(q =>
{
q.UseSimpleTypeLoader();
});
//获取所有Service业务层进行扫描注入
//业务层命名格式:Wood.xxx.Service
//需要注释的情况下在 Service 业务层开启 xml注释 生成
Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies().Where(it => !string.IsNullOrEmpty(it.FullName) && it.FullName.StartsWith("Wood") && it.FullName.Contains(".Service,")).ToArray();
//扫描依赖注入
services.ScanAndRegisterLifeTimes(assembly);
//swagger
services.AddSwaggerGen(options =>
{
foreach (var item in assembly)
{
var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{item.GetName().Name}.xml");
if (File.Exists(xmlPath))
options.IncludeXmlComments(xmlPath, true);
options.SwaggerDoc(item.GetName().Name, new OpenApiInfo { Title = "Wood Api", Version = "v1" });
}
//根据不同程序集生成不同分组
options.DocInclusionPredicate((docName, apiDesc) =>
{
return apiDesc.ActionDescriptor.DisplayName?.Contains(docName) ?? false;
});
#region swagger 身份验证
// 创建一个新的安全方案对象,用于描述如何进行身份验证。
var securityScheme = new OpenApiSecurityScheme
{
// 设置安全方案的名称,通常与 HTTP 请求头字段匹配。
Name = "Authorization",
// 指定安全方案的类型为 API 密钥(在这里特指 JWT Bearer Token)。
Type = SecuritySchemeType.ApiKey,
// 指定 API 密钥的位置,这里是 HTTP 请求头。
In = ParameterLocation.Header,
// 提供关于如何使用该安全方案的说明,例如在 Swagger UI 中显示给用户。
Description = "请在头信息中使用JWT Token进行身份验证 (例如: 'Bearer YOUR_TOKEN_HERE')",
// 设置安全方案的模式,这里是 Bearer 类型的身份验证。
Scheme = "Bearer",
// 设置 Bearer Token 的格式,这里指定为 JWT。
//BearerFormat = "JWT"
};
// 将创建的安全方案添加到 Swagger 文档中,以便 Swagger UI 可以识别并应用它。
options.AddSecurityDefinition("Bearer", securityScheme);
// 添加安全要求
// 添加Jwt验证设置,添加请求头信息
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
}
},
new List<string>()
}
});
options.OperationFilter<AddResponseHeadersFilter>();
options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
options.OperationFilter<SecurityRequirementsOperationFilter>();
#endregion
});
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseDeveloperExceptionPage();
}
//必须放在最前边 把 根 ServiceProvider 放入到全局
GlobalContext.ServiceProvider = app.ApplicationServices;
//初始化sqlsugar数据库结构
app.UseSqlSugar();
app.UseHangfireDashboard();
//自定义静态文件路径
//string resource = Path.Combine(env.ContentRootPath, "Resource");
//FileHelper.CreateDirectory(resource);
//app.UseStaticFiles(new StaticFileOptions
//{
// RequestPath = "/Resource",
// FileProvider = new PhysicalFileProvider(resource),
// OnPrepareResponse = GlobalContext.SetCacheControl
//});
app.UseStaticFiles();
//全局异常
app.UseMiddleware(typeof(GlobalExceptionMiddleware));
//文件拦截中间件
app.UseMiddleware<FileBridgeMiddleware>();
app.UseCors(builder =>
{
builder.WithOrigins(GlobalContext.SystemConfig!.AllowCorsSite.Split(',')).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
app.UseRouting();
// 使用身份验证中间件
app.UseAuthentication();
// 使用授权中间件
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "{controller=ApiHome}/{action=Index}/{id?}");
});
//启用 自动job
app.UseAutoJob();
//获取所有Service业务层 扫描事件
//业务层命名格式:Wood.xxx.Service
Assembly[] assembly = AppDomain.CurrentDomain.GetAssemblies().Where(it => !string.IsNullOrEmpty(it.FullName) && it.FullName.StartsWith("Wood") && it.FullName.Contains(".Service,")).ToArray();
app.UseSwagger(c =>
{
c.RouteTemplate = "api-doc/{documentName}/swagger.json";
});
//根据程序集注册选项
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "api-doc";
foreach (var assembly in assembly)
c.SwaggerEndpoint(assembly.GetName().Name + "/swagger.json", "Wood Api " + assembly.GetName().Name);
});
//自动 注册所有事件
app.UseEventBus(assembly);
}
}
}

61
API/Wood.Admin.WebApi/Wood.Admin.WebApi.csproj

@ -0,0 +1,61 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyVersion>3.1.0.0</AssemblyVersion>
<FileVersion>3.1.0.0</FileVersion>
<Copyright>WoodAdmin</Copyright>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>Wood.Admin.WebApi.xml</DocumentationFile>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Remove="wwwroot\DataSeed.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Quartz" Version="3.13.1" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.13.1" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="7.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="7.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TaskManager.Contracts\TaskManager.Contracts.csproj" />
<ProjectReference Include="..\TaskManager.EntityFramework\TaskManager.EntityFramework.csproj" />
<ProjectReference Include="..\TaskManager.Entity\TaskManager.Entity.csproj" />
<ProjectReference Include="..\Wood.AutoJob\Wood.AutoJob.csproj" />
<ProjectReference Include="..\Wood.Cache\Wood.Cache.Interface\Wood.Cache.Interface.csproj" />
<ProjectReference Include="..\Wood.Cache\Wood.MemoryCache\Wood.MemoryCache.csproj" />
<ProjectReference Include="..\Wood.Cache\Wood.RedisCache\Wood.RedisCache.csproj" />
<ProjectReference Include="..\Wood.Entity\Wood.Entity.csproj" />
<ProjectReference Include="..\Wood.Service\Wood.Service.csproj" />
<ProjectReference Include="..\Wood.Test.Service\Wood.Test.Service.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="DataSeed.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

9
API/Wood.Admin.WebApi/appsettings.Development.json

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

32
API/Wood.Admin.WebApi/appsettings.json

@ -0,0 +1,32 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug", // Trace,Debug,Information,Warning,Error,Critical
"System": "Information",
"Microsoft": "Information"
}
},
"AllowedHosts": "*",
"SystemConfig": {
"AllowCorsSite": "http://127.0.0.1:7005", // 访Api
"CacheProvider": "Memory", // 使 Memory Redis
"RedisConnectionString": "127.0.0.1:6379", //redis
"EnableInitDb": true, //,
"SnowFlakeWorkerId": 2, // SnowFlake id
"DBProvider": "Sqlite", // sqlsugar
"DBConnectionString": "Data Source=../WoodAdmin.db",
"DBCommandTimeout": 180, //
"DBBackup": "", //
"DBEnableDiffLog": true, //
"LogDays": 90, //
"RunAutoJob": true, //job
"CustomerDb": "Server = 192.168.1.228; Database = TaskManager1; User ID = sa; Password = ChangkeTec@2021; TrustServerCertificate = True"
},
"JwtConfig": {
"SecretKey": "3c1cac3f546eda35168c3aa3cn91780fbe703f0996c6d123ea96dc85c70bbc0a", // string 16
"Issuer": "WebAppIssuer", // string
"Audience": "WebAppAudience", // string
"RefreshTokenExpire": 15, //token
"TokenExpire": 30 //token
}
}

BIN
API/Wood.Admin.WebApi/wwwroot/template/用户信息导入模板.xlsx

Binary file not shown.

74
API/Wood.AutoJob/Attributes/CronAttribute.cs

@ -0,0 +1,74 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wood.AutoJob
{
/// <summary>
/// Cron表达式
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class CronAttribute : Attribute
{
public CronAttribute(string args)
{
this.Args = args;
}
/// <summary>
/// 触发器Id
/// </summary>
public string? TriggerId { get; set; }
/// <summary>
/// 参数
/// 运行时间间隔
/// </summary>
public string? Args { get; private set; }
/// <summary>
/// 描述信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 起始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 最大触发次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfRuns { get; set; } = 0;
/// <summary>
/// 最大出错次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfErrors { get; set; } = 0;
/// <summary>
/// 重试次数
/// </summary>
public int NumRetries { get; set; }
/// <summary>
/// 重试间隔时间(ms)
/// </summary>
public int RetryTimeout { get; set; } = 60000;
/// <summary>
/// 是否启动时执行一次
/// </summary>
public bool RunOnStart { get; set; } = false;
}
}

75
API/Wood.AutoJob/Attributes/DailyAtAttribute.cs

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wood.AutoJob
{
/// <summary>
/// 每天x点执行
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class DailyAtAttribute : Attribute
{
/// <summary>
///
/// </summary>
/// <param name="args">示例1:00:00 (0点0分执行) 示例2:23(23点执行)</param>
public DailyAtAttribute(string args)
{
this.Args = args;
}
/// <summary>
/// 触发器Id
/// </summary>
public string? TriggerId { get; set; }
/// <summary>
/// 参数
/// 运行时间间隔
/// </summary>
public string? Args { get; private set; }
/// <summary>
/// 描述信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 起始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 最大触发次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfRuns { get; set; } = 0;
/// <summary>
/// 最大出错次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfErrors { get; set; } = 0;
/// <summary>
/// 重试次数
/// </summary>
public int NumRetries { get; set; }
/// <summary>
/// 重试间隔时间(ms)
/// </summary>
public int RetryTimeout { get; set; } = 60000;
/// <summary>
/// 是否启动时执行一次
/// </summary>
public bool RunOnStart { get; set; } = false;
}
}

31
API/Wood.AutoJob/Attributes/JobDetailAttribute.cs

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wood.Entity.SystemManage;
namespace Wood.AutoJob
{
/// <summary>
/// Job明细
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class JobDetailAttribute : Attribute
{
/// <summary>
/// 作业Id
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 组名称
/// </summary>
public string? GroupName { get; set; } = "default";
/// <summary>
/// 描述信息
/// </summary>
public string? Description { get; set; }
}
}

72
API/Wood.AutoJob/Attributes/PeriodMinutesAttribute.cs

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wood.AutoJob
{
/// <summary>
/// 每X分钟执行
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class PeriodMinutesAttribute : Attribute
{
public PeriodMinutesAttribute(int args)
{
this.Args = args.ToString();
}
/// <summary>
/// 触发器Id
/// </summary>
public string? TriggerId { get; set; }
/// <summary>
/// 参数
/// 运行时间间隔
/// </summary>
public string? Args { get;private set; }
/// <summary>
/// 描述信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 起始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 最大触发次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfRuns { get; set; } = 0;
/// <summary>
/// 最大出错次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfErrors { get; set; } = 0;
/// <summary>
/// 重试次数
/// </summary>
public int NumRetries { get; set; }
/// <summary>
/// 重试间隔时间(ms)
/// </summary>
public int RetryTimeout { get; set; } = 60000;
/// <summary>
/// 是否启动时执行一次
/// </summary>
public bool RunOnStart { get; set; } = false;
}
}

73
API/Wood.AutoJob/Attributes/PeriodSecondsAttribute.cs

@ -0,0 +1,73 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wood.Entity;
namespace Wood.AutoJob
{
/// <summary>
/// 每X秒执行
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class PeriodSecondsAttribute:Attribute
{
public PeriodSecondsAttribute(int args)
{
this.Args = args.ToString();
}
/// <summary>
/// 触发器Id
/// </summary>
public string? TriggerId { get; set; }
/// <summary>
/// 参数
/// 运行时间间隔
/// </summary>
public string? Args { get; private set; }
/// <summary>
/// 描述信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 起始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 最大触发次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfRuns { get; set; } = 0;
/// <summary>
/// 最大出错次数(0:不限制,n:N次)
/// </summary>
public long MaxNumberOfErrors { get; set; } = 0;
/// <summary>
/// 重试次数
/// </summary>
public int NumRetries { get; set; }
/// <summary>
/// 重试间隔时间(ms)
/// </summary>
public int RetryTimeout { get; set; } = 60000;
/// <summary>
/// 是否启动时执行一次
/// </summary>
public bool RunOnStart { get; set; } = false;
}
}

279
API/Wood.AutoJob/AutoJobCenter.cs

@ -0,0 +1,279 @@
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using System.Reflection;
using Wood.Data.Repository;
using Wood.Entity;
using Wood.Entity.SystemManage;
using Wood.EventBus;
using Wood.Util;
namespace Wood.AutoJob
{
public class AutoJobCenter
{
#region 扫描任务计划
public async void ScanJob()
{
using var scope = GlobalContext.ServiceProvider!.CreateScope();
var jobTriggerRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<JobTriggerEntity>>();
var jobDetailRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<JobDetailEntity>>();
var eventBus = scope.ServiceProvider.GetRequiredService<IEventBus>();
var types = Assembly.GetAssembly(typeof(AutoJobCenter))!.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttributes(typeof(JobDetailAttribute), false).Any())
.ToList();
foreach (var item in types)
{
string jobId = "";
var jobDetailAttr = item.GetCustomAttribute<JobDetailAttribute>();
if (jobDetailAttr != null)
{
var detail = jobDetailAttr.Adapt<JobDetailEntity>();
detail.JobType = item.FullName;
detail.AssemblyName = item.Assembly.FullName;
jobId = detail.JobId!;
var dbDetail = await jobDetailRepository.GetFirstAsync(it => it.JobId == detail.JobId);
if (!jobDetailRepository.IsAny(it => it.JobId == detail.JobId))
jobDetailRepository.Insert(detail);
else
{
if (dbDetail.Description != detail.Description || dbDetail.GroupName != detail.GroupName)
{
dbDetail.GroupName = detail.GroupName;
dbDetail.Description = detail.Description;
await jobDetailRepository.UpdateAsync(dbDetail);
}
}
}
else
continue;
var secondsAtAttr = item.GetCustomAttribute<PeriodSecondsAttribute>();
JobTriggerEntity? entity = null;
if (secondsAtAttr != null && entity == null)
{
entity = secondsAtAttr.Adapt<JobTriggerEntity>();
entity.TriggerType = TriggerTypeEnum.PeriodSeconds;
}
var minutesAttr = item.GetCustomAttribute<PeriodMinutesAttribute>();
if (minutesAttr != null && entity == null)
{
entity = minutesAttr.Adapt<JobTriggerEntity>();
entity.TriggerType = TriggerTypeEnum.PeriodMinutes;
}
var dailyAtAttr = item.GetCustomAttribute<DailyAtAttribute>();
if (dailyAtAttr != null && entity == null)
{
entity = dailyAtAttr.Adapt<JobTriggerEntity>();
entity.TriggerType = TriggerTypeEnum.DailyAt;
}
var cronAttr = item.GetCustomAttribute<CronAttribute>();
if (cronAttr != null && entity == null)
{
entity = cronAttr.Adapt<JobTriggerEntity>();
entity.TriggerType = TriggerTypeEnum.Cron;
}
if (entity != null)
{
entity.JobId = jobId;
entity.Status = TriggerStatusEnum.Ready;
var trigger = jobTriggerRepository.GetFirst(it => it.TriggerId == entity.TriggerId);
if (trigger == null)
jobTriggerRepository.Insert(entity);
else
{
//只有触发器类型 或者 参数 或者 说明 变更时需要更新触发器数据
if (trigger.TriggerType != entity.TriggerType || trigger.Args != entity.Args || trigger.Description != entity.Description)
{
entity.Id = trigger.Id;
entity.CreateTime = trigger.CreateTime;
entity.CreateUserId = trigger.CreateUserId;
jobTriggerRepository.Update(entity.Adapt(trigger));
}
}
}
}
}
#endregion
#region 添加任务计划
public async Task AddScheduleJob()
{
using var scope = GlobalContext.ServiceProvider!.CreateScope();
var schedulerFactory = scope.ServiceProvider.GetRequiredService<ISchedulerFactory>();
var jobTriggerRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<JobTriggerEntity>>();
var jobDetailRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<JobDetailEntity>>();
var jobDetailList = jobDetailRepository.AsQueryable().ClearFilter().ToList();
var scheduler = await schedulerFactory.GetScheduler();
foreach (var detail in jobDetailList)
{
var jobTrigger = await jobTriggerRepository.GetFirstAsync(it => it.JobId == detail.JobId);
var jobType = this.GetType().Assembly.GetType(detail.JobType!);
if (jobType != null)
{
IJobDetail job = JobBuilder.Create(jobType!).WithIdentity(detail.JobId!, detail.GroupName!).Build();
job.JobDataMap.Add("DetailId", detail.Id);
job.JobDataMap.Add("TriggerId", jobTrigger.Id);
var trigger = CreateTrigger(jobTrigger, detail);
//更新下次执行时间
jobTrigger.NextRunTime = trigger.GetNextFireTimeUtc()?.DateTime.AddHours(8);
jobTrigger.Status = TriggerStatusEnum.Ready;
await jobTriggerRepository.UpdateAsync(jobTrigger);
await scheduler.ScheduleJob(job, CreateTrigger(jobTrigger, detail));
}
else
{
jobTrigger.Status = TriggerStatusEnum.Ineffective;
await jobTriggerRepository.UpdateAsync(jobTrigger);
}
}
await scheduler.Start();
}
/// <summary>
/// 创建trigger
/// </summary>
/// <param name="jobTrigger"></param>
/// <param name="jobDetail"></param>
/// <returns></returns>
public static ITrigger CreateTrigger(JobTriggerEntity jobTrigger, JobDetailEntity jobDetail)
{
/*
* Cron
withMisfireHandlingInstructionFireAndProceed [MISFIRE_INSTRUCTION_FIRE_ONCE_NOW]
Cron频率依次执行
withMisfireHandlingInstructionDoNothing [MISFIRE_INSTRUCTION_DO_NOTHING ]
Cron触发频率到达时刻开始按照Cron频率依次执行
withMisfireHandlingInstructionIgnoreMisfires [MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY]
Cron频率依次执行
:
WithSimpleSchedule
withMisfireHandlingInstructionNowWithExistingCount
FinalTIme的剩余周期次数
FinalTime根据剩余次数和当前时间计算得到
FinalTime会略大于根据starttime计算的到的FinalTime值
withMisfireHandlingInstructionFireNow
FinalTIme的剩余周期次数
FinalTime根据剩余次数和当前时间计算得到
FinalTime会略大于根据starttime计算的到的FinalTime值
withMisfireHandlingInstructionIgnoreMisfires
Interval的依次执行剩下的频率
RepeatCount+1
withMisfireHandlingInstructionNextWithExistingCount
FinalTime的剩余周期次数
startTime为基准计算周期频率FinalTime
使pauseresume以后保持FinalTime时间不变
withMisfireHandlingInstructionNextWithRemainingCount
FinalTime的剩余周期次数
startTime为基准计算周期频率FinalTime
使pauseresume以后保持FinalTime时间不变
withMisfireHandlingInstructionNowWithRemainingCount
FinalTIme的剩余周期次数
FinalTime根据剩余次数和当前时间计算得到
FinalTime会略大于根据starttime计算的到的FinalTime值
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
trigger忘记原始设置的starttime和repeat-count
repeat-count将被设置为剩余的次数
starttime和repeat-count值
*/
if (jobTrigger.StartTime == null)
jobTrigger.StartTime = DateTime.Now;
DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(jobTrigger.StartTime, 1);
TriggerBuilder triggerBuilder = TriggerBuilder.Create()
.WithIdentity(jobTrigger.TriggerId!, jobDetail.GroupName!);
if (jobTrigger.TriggerType == Entity.TriggerTypeEnum.DailyAt)
{
string[] times = jobTrigger.Args!.Split(":");
if (times.Length == 1)
{
if (!jobTrigger.RunOnStart)
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule($"0 0 {times[0]} * * ?", x => x.WithMisfireHandlingInstructionDoNothing());
else
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule($"0 0 {times[0]} * * ?", x => x.WithMisfireHandlingInstructionFireAndProceed());
}
else
{
if (!jobTrigger.RunOnStart)
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule($"0 {times[1]} {times[0]} * * ?", x => x.WithMisfireHandlingInstructionDoNothing());
else
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule($"0 {times[1]} {times[0]} * * ?", x => x.WithMisfireHandlingInstructionFireAndProceed());
}
}
else if (jobTrigger.TriggerType == Entity.TriggerTypeEnum.PeriodMinutes)
{
int interval = jobTrigger.Args!.ToInt();
if (!jobTrigger.RunOnStart)
starRunTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddMinutes(interval), 1);
triggerBuilder = triggerBuilder.StartAt(starRunTime)
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(interval) // 每xm分钟重复一次
.RepeatForever()); // 无限重复;
}
else if (jobTrigger.TriggerType == Entity.TriggerTypeEnum.PeriodSeconds)
{
int interval = jobTrigger.Args!.ToInt();
if (!jobTrigger.RunOnStart)
starRunTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddSeconds(interval), 1);
triggerBuilder = triggerBuilder.WithSimpleSchedule(x => x
.WithIntervalInSeconds(interval) // 每x秒重复一次
.RepeatForever()); // 无限重复;
}
else if (jobTrigger.TriggerType == Entity.TriggerTypeEnum.Cron)
{
if (!jobTrigger.RunOnStart)
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule(jobTrigger.Args!, x => x.WithMisfireHandlingInstructionDoNothing());
else
triggerBuilder = triggerBuilder.StartAt(starRunTime).WithCronSchedule(jobTrigger.Args!, x => x.WithMisfireHandlingInstructionFireAndProceed());
}
else
throw Oops.Oh("AutoJob不支持的触发器类型!");
return triggerBuilder!.Build();
}
#endregion
}
}

157
API/Wood.AutoJob/AutoJobTask.cs

@ -0,0 +1,157 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Serilog;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Wood.Data.Repository;
using Wood.Entity;
using Wood.Entity.SystemManage;
using Wood.EventBus;
using Wood.EventBus.Events;
using Wood.Util;
namespace Wood.AutoJob
{
public abstract class AutoJobTask : IJob
{
/// <summary>
/// 执行逻辑
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public virtual Task Run(IJobExecutionContext context, IServiceProvider provider)
{
throw new NotImplementedException();
}
public async Task Execute(IJobExecutionContext context)
{
DateTime now = DateTime.Now;
using var scope = GlobalContext.ServiceProvider!.CreateScope();
var jobTriggerRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<JobTriggerEntity>>();
var eventBus = scope.ServiceProvider.GetRequiredService<IEventBus>();
var logJobRepository = scope.ServiceProvider.GetRequiredService<SqlSugarRepository<LogJobEntity>>();
JobDataMap jobData = context.JobDetail.JobDataMap;
long detailId = jobData["DetailId"].ToString()?.ToLong() ?? 0;
long triggerId = jobData["TriggerId"].ToString()?.ToLong() ?? 0;
// 获取数据库中的任务
JobTriggerEntity triggerEntity = await jobTriggerRepository.GetByIdAsync(triggerId);
if (triggerEntity != null)
{
var logJob = new LogJobEntity()
{
Elapsed=0,
TriggerId = triggerEntity.TriggerId,
JobId = triggerEntity.JobId,
RetryCount=0,
RunTime = now,
};
var planRuntime = triggerEntity.NextRunTime;
triggerEntity.LastRunTime = now;
triggerEntity.NextRunTime = context.NextFireTimeUtc?.DateTime.AddHours(8);
//任务已经暂停
if (triggerEntity.Status == TriggerStatusEnum.Pause ||
triggerEntity.Status == TriggerStatusEnum.Archived ||
triggerEntity.Status == TriggerStatusEnum.Overrun ||
triggerEntity.Status == TriggerStatusEnum.Panic
)
{
//job 更新下次执行事时间
logJob.Status = triggerEntity.Status.GetDescription();
await logJobRepository.InsertAsync(logJob);
await jobTriggerRepository.UpdateAsync(triggerEntity);
return;
}
else if (triggerEntity.Status == TriggerStatusEnum.Running)
{
//上个任务正在实行 设置为 阻塞
triggerEntity.Status = TriggerStatusEnum.Blocked;
logJob.Status = triggerEntity.Status.GetDescription();
await logJobRepository.InsertAsync(logJob);
await jobTriggerRepository.UpdateAsync(triggerEntity);
return;
}
else if (triggerEntity.EndTime.HasValue && now > triggerEntity.EndTime.Value)
{
//超过任务结束时间 设置为归档
triggerEntity.Status = TriggerStatusEnum.Archived;
logJob.Status = triggerEntity.Status.GetDescription();
await logJobRepository.InsertAsync(logJob);
await jobTriggerRepository.UpdateAsync(triggerEntity);
return;
}
else
{
triggerEntity.NumberOfRuns++;
Stopwatch stopwatch = Stopwatch.StartNew();
//重试次数
int i = 0;
string status = triggerEntity.Status.GetDescription();
//只有在 就绪状态才能继续执行
if (triggerEntity.Status == TriggerStatusEnum.ErrorToReady || triggerEntity.Status == TriggerStatusEnum.Ready || triggerEntity.Status == TriggerStatusEnum.Blocked)
{
triggerEntity.Status = TriggerStatusEnum.Running; //正常开始运行
//执行前 job更新状态
await jobTriggerRepository.UpdateAsync(triggerEntity);
//设置重试次数,最小执行一次
int retryCount = triggerEntity.NumRetries;
if (triggerEntity.NumRetries == 0)
retryCount = 1;
for (; i < retryCount; i++)
{
try
{
//执行逻辑
await Run(context, scope.ServiceProvider);
status = "执行完成";
if (triggerEntity.MaxNumberOfRuns > 0 && triggerEntity.MaxNumberOfRuns <= triggerEntity.NumberOfRuns)
triggerEntity.Status = TriggerStatusEnum.Overrun;
else
triggerEntity.Status = TriggerStatusEnum.Ready;
break;
}
catch (Exception ex)
{
status = "执行出错";
//记录错误信息
eventBus.Publish(LogExceptionEvent.NewEvent(ex, triggerEntity.JobId!, triggerEntity.TriggerId!, "Execute"));
//出现错误
triggerEntity.NumberOfErrors++;
if (triggerEntity.MaxNumberOfErrors > 0 && triggerEntity.MaxNumberOfErrors < triggerEntity.NumberOfErrors)
triggerEntity.Status = TriggerStatusEnum.Panic;
else
triggerEntity.Status = TriggerStatusEnum.ErrorToReady;
Log.Error(ex, $"执行job出错!【{triggerEntity.JobId}】");
}
await Task.Delay(triggerEntity.RetryTimeout);
}
}
stopwatch.Stop();
logJob.Elapsed = stopwatch.ElapsedMilliseconds;
logJob.Status = "正常执行";
logJob.RetryCount = i;
await logJobRepository.InsertAsync(logJob);
//job 执行完 更新状态
await jobTriggerRepository.UpdateAsync(triggerEntity);
}
}
}
}
}

37
API/Wood.AutoJob/Job/DBLogClearJob.cs

@ -0,0 +1,37 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Wood.Data.Repository;
using Wood.Entity.SystemManage;
using Wood.Util;
namespace Wood.AutoJob
{
/// <summary>
/// 日志清理job
/// </summary>
[JobDetail(JobId = "job_DBLogClear", GroupName = "system", Description = "清理日志")]
[PeriodMinutes(480, TriggerId = "trigger_DBLogClear")]
[DisallowConcurrentExecution]
public class DBLogClearJob : AutoJobTask
{
public override async Task Run(IJobExecutionContext context, IServiceProvider serviceProvider)
{
DateTime startTime = DateTime.Now.AddDays(0 - GlobalContext.SystemConfig!.LogDays);
var ldRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogDiffEntity>>();
var levRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogEventEntity>>();
var lexRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogExceptionEntity>>();
var ljRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogJobEntity>>();
var llRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogLoginEntity>>();
var loRepository = serviceProvider.GetRequiredService<SqlSugarRepository<LogOperationEntity>>();
await ldRepository.DeleteAsync(it => it.CreateTime < startTime);
await levRepository.DeleteAsync(it => it.CreateTime < startTime);
await lexRepository.DeleteAsync(it => it.CreateTime < startTime);
await ljRepository.DeleteAsync(it => it.CreateTime < startTime);
await llRepository.DeleteAsync(it => it.CreateTime < startTime);
await loRepository.DeleteAsync(it => it.CreateTime < startTime);
}
}
}

21
API/Wood.AutoJob/Wood.AutoJob.csproj

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quartz" Version="3.13.1" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wood.Data.Repository\Wood.Data.Repository.csproj" />
<ProjectReference Include="..\Wood.Entity\Wood.Entity.csproj" />
<ProjectReference Include="..\Wood.EventBus\Wood.EventBus.csproj" />
<ProjectReference Include="..\Wood.Util\Wood.Util.csproj" />
</ItemGroup>
</Project>

27
API/Wood.Cache/Wood.Cache.Interface/ICache.cs

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace Wood.Cache
{
public interface ICache
{
bool SetCache<T>(string key, T value, DateTime? expireTime = null);
T? GetCache<T>(string key);
bool TryGetCache<T>(string key,out T? val);
bool RemoveCache(string key);
#region Hash
int SetHashFieldCache<T>(string key, string fieldKey, T fieldValue);
int SetHashFieldCache<T>(string key, Dictionary<string, T> dict);
T GetHashFieldCache<T>(string key, string fieldKey);
Dictionary<string, T> GetHashFieldCache<T>(string key, Dictionary<string, T> dict);
Dictionary<string, T> GetHashCache<T>(string key);
List<T> GetHashToListCache<T>(string key);
bool RemoveHashFieldCache(string key, string fieldKey);
Dictionary<string, bool> RemoveHashFieldCache(string key, Dictionary<string, bool> dict);
#endregion
}
}

14
API/Wood.Cache/Wood.Cache.Interface/Wood.Cache.Interface.csproj

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
</Project>

126
API/Wood.Cache/Wood.MemoryCache/MemoryCacheImp.cs

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Caching.Memory;
using Wood.Cache;
using Wood.Util;
using Serilog;
namespace Wood.MemoryCache
{
public class MemoryCacheImp : ICache
{
private IMemoryCache cache = GlobalContext.ServiceProvider!.GetService<IMemoryCache>()!;
public bool SetCache<T>(string key, T value, DateTime? expireTime = null)
{
try
{
if (expireTime == null)
{
return cache.Set<T>(key, value) != null;
}
else
{
return cache.Set(key, value, (expireTime.Value - DateTime.Now)) != null;
}
}
catch (Exception ex)
{
Log.Error(ex, "设置缓存失败:key({key})", key);
}
return false;
}
public bool RemoveCache(string key)
{
cache.Remove(key);
return true;
}
public T? GetCache<T>(string key)
{
var value = cache.Get<T>(key)!;
return value;
}
public bool TryGetCache<T>(string key,out T? val)
{
var value = cache.TryGetValue<T>(key,out val)!;
return value;
}
#region Hash
public int SetHashFieldCache<T>(string key, string fieldKey, T fieldValue)
{
return SetHashFieldCache<T>(key, new Dictionary<string, T> { { fieldKey, fieldValue } });
}
public int SetHashFieldCache<T>(string key, Dictionary<string, T> dict)
{
int count = 0;
foreach (string fieldKey in dict.Keys)
{
count += cache.Set(key, dict) != null ? 1 : 0;
}
return count;
}
public T GetHashFieldCache<T>(string key, string fieldKey)
{
var dict = GetHashFieldCache<T>(key, new Dictionary<string, T> { { fieldKey, default(T)! } });
return dict[fieldKey];
}
public Dictionary<string, T> GetHashFieldCache<T>(string key, Dictionary<string, T> dict)
{
var hashFields = cache.Get<Dictionary<string, T>>(key);
foreach (KeyValuePair<string, T> keyValuePair in hashFields!.Where(p => dict.Keys.Contains(p.Key)))
{
dict[keyValuePair.Key] = keyValuePair.Value;
}
return dict;
}
public Dictionary<string, T> GetHashCache<T>(string key)
{
Dictionary<string, T> dict = new Dictionary<string, T>();
var hashFields = cache.Get<Dictionary<string, T>>(key);
foreach (string field in hashFields!.Keys)
{
dict[field] = hashFields[field];
}
return dict;
}
public List<T> GetHashToListCache<T>(string key)
{
List<T> list = new List<T>();
var hashFields = cache.Get<Dictionary<string, T>>(key);
foreach (string field in hashFields!.Keys)
{
list.Add(hashFields[field]);
}
return list;
}
public bool RemoveHashFieldCache(string key, string fieldKey)
{
Dictionary<string, bool> dict = new Dictionary<string, bool> { { fieldKey, false } };
dict = RemoveHashFieldCache(key, dict);
return dict[fieldKey];
}
public Dictionary<string, bool> RemoveHashFieldCache(string key, Dictionary<string, bool> dict)
{
var hashFields = cache.Get<Dictionary<string, object>>(key);
foreach (string fieldKey in dict.Keys)
{
dict[fieldKey] = hashFields!.Remove(fieldKey);
}
return dict;
}
#endregion
}
}

20
API/Wood.Cache/Wood.MemoryCache/Wood.MemoryCache.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Wood.Util\Wood.Util.csproj" />
<ProjectReference Include="..\Wood.Cache.Interface\Wood.Cache.Interface.csproj" />
</ItemGroup>
</Project>

188
API/Wood.Cache/Wood.RedisCache/RedisCacheImp.cs

@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Serilog;
using StackExchange.Redis;
using Wood.Cache;
using Wood.Util;
namespace Wood.RedisCache
{
public class RedisCacheImp : ICache
{
private IDatabase cache;
private ConnectionMultiplexer connection;
public RedisCacheImp()
{
connection = ConnectionMultiplexer.Connect(GlobalContext.SystemConfig!.RedisConnectionString);
cache = connection.GetDatabase();
}
public bool SetCache<T>(string key, T value, DateTime? expireTime = null)
{
try
{
var jsonOption = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string strValue = JsonConvert.SerializeObject(value, jsonOption);
if (string.IsNullOrEmpty(strValue))
{
return false;
}
if (expireTime == null)
{
return cache.StringSet(key, strValue);
}
else
{
return cache.StringSet(key, strValue, (expireTime.Value - DateTime.Now));
}
}
catch (Exception ex)
{
Log.Error(ex,"设置缓存失败:key({key})",key);
}
return false;
}
public bool RemoveCache(string key)
{
return cache.KeyDelete(key);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public T? GetCache<T>(string key)
{
var t = default(T);
try
{
var value = cache.StringGet(key);
if (string.IsNullOrEmpty(value))
{
return t;
}
t = JsonConvert.DeserializeObject<T>(value!);
}
catch (Exception ex)
{
Log.Error(ex, "获取缓存失败:key({key})", key);
}
return t;
}
public bool TryGetCache<T>(string key,out T? val)
{
val = default(T);
try
{
var value = cache.StringGet(key);
if (string.IsNullOrEmpty(value))
{
return false;
}
val = JsonConvert.DeserializeObject<T>(value!);
return true;
}
catch (Exception ex)
{
Log.Error(ex, "获取缓存失败:key({key})", key);
}
return false;
}
#region Hash
public int SetHashFieldCache<T>(string key, string fieldKey, T fieldValue)
{
return SetHashFieldCache<T>(key, new Dictionary<string, T> { { fieldKey, fieldValue } });
}
public int SetHashFieldCache<T>(string key, Dictionary<string, T> dict)
{
int count = 0;
var jsonOption = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
foreach (string fieldKey in dict.Keys)
{
string fieldValue = JsonConvert.SerializeObject(dict[fieldKey], jsonOption);
count += cache.HashSet(key, fieldKey, fieldValue) ? 1 : 0;
}
return count;
}
public T GetHashFieldCache<T>(string key, string fieldKey)
{
var dict = GetHashFieldCache<T>(key, new Dictionary<string, T> { { fieldKey, default(T)! } });
return dict[fieldKey];
}
public Dictionary<string, T> GetHashFieldCache<T>(string key, Dictionary<string, T> dict)
{
foreach (string fieldKey in dict.Keys)
{
string? fieldValue = cache.HashGet(key, fieldKey);
if(fieldValue != null)
dict[fieldKey] = JsonConvert.DeserializeObject<T>(fieldValue)!;
}
return dict;
}
public Dictionary<string, T> GetHashCache<T>(string key)
{
Dictionary<string, T> dict = new Dictionary<string, T>();
var hashFields = cache.HashGetAll(key);
foreach (HashEntry field in hashFields)
{
dict[field.Name!] = JsonConvert.DeserializeObject<T>(field.Value!)!;
}
return dict;
}
public List<T> GetHashToListCache<T>(string key)
{
List<T> list = new List<T>();
var hashFields = cache.HashGetAll(key);
foreach (HashEntry field in hashFields)
{
list.Add(JsonConvert.DeserializeObject<T>(field.Value!)!);
}
return list;
}
public bool RemoveHashFieldCache(string key, string fieldKey)
{
Dictionary<string, bool> dict = new Dictionary<string, bool> { { fieldKey, false } };
dict = RemoveHashFieldCache(key, dict);
return dict[fieldKey];
}
public Dictionary<string, bool> RemoveHashFieldCache(string key, Dictionary<string, bool> dict)
{
foreach (string fieldKey in dict.Keys)
{
dict[fieldKey] = cache.HashDelete(key, fieldKey);
}
return dict;
}
#endregion
public void Dispose()
{
if (connection != null)
{
connection.Close();
}
GC.SuppressFinalize(this);
}
}
}

20
API/Wood.Cache/Wood.RedisCache/Wood.RedisCache.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Wood.Util\Wood.Util.csproj" />
<ProjectReference Include="..\Wood.Cache.Interface\Wood.Cache.Interface.csproj" />
</ItemGroup>
</Project>

31
API/Wood.Data.Repository/DataSeed/UserDataSeed.cs

@ -0,0 +1,31 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wood.Entity.SystemManage;
using Wood.Util;
namespace Wood.Data.Repository.DataSeed
{
public class UserDataSeed
{
public static void InitData(ISqlSugarClient db)
{
string dataSeedPath = Path.Combine(GlobalContext.HostingEnvironment!.ContentRootPath, "DataSeed.sql");
if (File.Exists(dataSeedPath))
{
var lines = File.ReadAllLines(dataSeedPath);
foreach (var item in lines)
{
if (item.StartsWith("INSERT"))
{
db.Ado.ExecuteCommand(item);
}
}
}
}
}
}

234
API/Wood.Data.Repository/DbContext/SqlSugarDbContext.cs

@ -0,0 +1,234 @@
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System.Data;
using System.Reflection;
using Wood.Cache;
using Wood.Data.Repository.DataSeed;
using Wood.Entity;
using Wood.Entity.SystemManage;
using Wood.Util;
namespace Wood.Data.Repository
{
public static class SqlSugarDbContext
{
#region aop
/// <summary>
/// 配置Aop
/// </summary>
/// <param name="db"></param>
public static void SetDbAop(SqlSugarProvider db)
{
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = GlobalContext.SystemConfig!.DBCommandTimeout;
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
Log.Information("【执行SQL】" + UtilMethods.GetSqlString(config.DbType, sql, pars));
};
db.Aop.OnError = ex =>
{
if (ex.Parametres == null) return;
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
Log.Error("【错误SQL】" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + Environment.NewLine + pars);
};
// 数据审计
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
var user = GlobalContext.UserInfo;
// 演示环境判断
if (entityInfo.OperationType == DataFilterType.InsertByObject)
{
// 主键(long类型)且没有值的---赋值雪花Id
if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
{
var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
if (id == null || (long)id == 0)
entityInfo.SetValue(IdGeneratorHelper.Instance.GetId());
}
if (entityInfo.PropertyName == "CreateTime")
entityInfo.SetValue(DateTime.Now);
if (user != null)
{
if (entityInfo.PropertyName == "TenantId")
{
var tenantId = ((dynamic)entityInfo.EntityValue).TenantId;
if (tenantId == null || tenantId == 0)
entityInfo.SetValue(user?.TenantId);
}
if (entityInfo.PropertyName == "CreateUserId")
{
var createUserId = ((dynamic)entityInfo.EntityValue).CreateUserId;
if (createUserId == 0 || createUserId == null)
entityInfo.SetValue(user?.UserId);
}
if (entityInfo.PropertyName == "CreateOrgId")
{
var createOrgId = ((dynamic)entityInfo.EntityValue).CreateOrgId;
if (createOrgId == 0 || createOrgId == null)
entityInfo.SetValue(user?.OrgId);
}
}
}
if (entityInfo.OperationType == DataFilterType.UpdateByObject)
{
if (entityInfo.PropertyName == "UpdateTime")
entityInfo.SetValue(DateTime.Now);
if (entityInfo.PropertyName == "UpdateUserId")
entityInfo.SetValue(user?.UserId);
}
};
// 配置实体假删除过滤器
db.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDelete == false);
var user = GlobalContext.UserInfo;
// 超管 排除过滤器
if (user != null && user.IsSuperAdmin)
return;
// 配置租户过滤器
var tenantId = user?.TenantId;
if (tenantId > 0)
db.QueryFilter.AddTableFilter<ITenantIdFilter>(u => u.TenantId == tenantId);
// 配置用户机构(数据范围)过滤器
if (user != null)
{
if (!user.IsAdmin)
{
var icache = GlobalContext.ServiceProvider!.GetRequiredService<ICache>();
var userCache = icache.GetCache<UserCache>(user.CacheKey);
if (userCache != null)
{
//根据org列表筛选数据
if (userCache!.DataScopeType == DataScopeTypeEnum.Custom ||
userCache!.DataScopeType == DataScopeTypeEnum.MyOrg ||
userCache!.DataScopeType == DataScopeTypeEnum.MyOrgAndLower)
db.QueryFilter.AddTableFilter<IOrgIdFilter>(u => userCache.DataScopeOrgs.Contains(u.CreateOrgId!.Value));
//仅本人数据过滤器
//本人创建,而且在本人所属部门的数据
else if (userCache!.DataScopeType == DataScopeTypeEnum.MySelf)
{
db.QueryFilter.AddTableFilter<IOrgIdFilter>(u => u.CreateOrgId!.Value == userCache.OrgId);
db.QueryFilter.AddTableFilter<ICreateUserIdFilter>(u => u.CreateUserId!.Value == userCache.Id);
}
}
// else 全部数据不做筛选
}
}
// 其他配置自定义过滤器
}
/// <summary>
/// 开启库表差异化日志
/// </summary>
/// <param name="db"></param>
/// <param name="config"></param>
public static void SetDbDiffLog(SqlSugarProvider db)
{
if (!GlobalContext.SystemConfig!.DBEnableDiffLog)
return;
//程序启动时注册 开启差异化记录
StaticConfig.CompleteInsertableFunc =
StaticConfig.CompleteUpdateableFunc =
StaticConfig.CompleteDeleteableFunc = obj => //it是具体的对象Updateable<T>等是个object
{
//反射的方法可能多个就需要用GetMethods().Where
if (obj.GetType().GenericTypeArguments[0].GetInterfaces().Any(it => it == typeof(IDiff)))
{
var method = obj.GetType().GetMethod("EnableDiffLogEvent");
method?.Invoke(obj, new object?[] { null });
}
//技巧:
//可以定义一个接口只要是这个接口的才走这个逻辑
//if(db.GetType().GenericTypeArguments[0].GetInterfaces().Any(it=>it==typeof(IDiff))
//可以根据类型写if
//if(x.GetType().GenericTypeArguments[0] = typeof(Order)) { }
};
db.Aop.OnDiffLogEvent = async u =>
{
var tables = u.AfterData.Select(it => it.TableName).Distinct();
if(u.BeforeData!=null)
tables = tables.Union(u.BeforeData.Select(it => it.TableName)).Distinct();
var logDiff = new LogDiffEntity
{
Tables = string.Join(", ", tables),
// 操作后记录(字段描述、列名、值、表名、表描述)
AfterData = JsonConvert.SerializeObject(u.AfterData),
// 操作前记录(字段描述、列名、值、表名、表描述)
BeforeData = (u.BeforeData != null ? JsonConvert.SerializeObject(u.BeforeData) : null),
// 传进来的对象
BusinessData = JsonConvert.SerializeObject(u.BusinessData),
// 枚举(insert、update、delete)
DiffType = u.DiffType.ToString(),
Sql = UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, u.Sql, u.Parameters),
Parameters = JsonConvert.SerializeObject(u.Parameters),
Elapsed = u.Time == null ? 0 : (long)u.Time.Value.TotalMilliseconds
};
//防止表格过多入库失败
if (logDiff.Tables.Length > 256)
logDiff.Tables = logDiff.Tables.Substring(255);
await db.Insertable(logDiff).ExecuteCommandAsync();
Log.Information($"*****差异日志开始*****{Environment.NewLine}{Environment.NewLine}{JsonConvert.SerializeObject(logDiff)}{Environment.NewLine}*****差异日志结束*****");
};
}
#endregion
#region 初始化
/// <summary>
/// 初始化数据库
/// </summary>
/// <param name="db"></param>
public static void InitDatabase(ISqlSugarClient db)
{
if (!GlobalContext.SystemConfig!.EnableInitDb) return;
var dbProvider = db;
// 创建数据库
if (db.CurrentConnectionConfig.DbType != SqlSugar.DbType.Oracle)
{
dbProvider.DbMaintenance.CreateDatabase();
}
var tables = dbProvider.DbMaintenance.GetTableInfoList();
// 获取所有实体表-初始化表结构
var entityTypes = Assembly.GetAssembly(typeof(EntityBase))!.GetTypes().Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)).ToList();
if (!entityTypes.Any()) return;
foreach (var entityType in entityTypes)
{
var sugarTable = entityType.GetCustomAttribute<SugarTable>();
//只有首次创建的表需要初始化
//变更请通过手动处理
if (!tables.Any(it => string.Equals(it.Name, sugarTable!.TableName, StringComparison.OrdinalIgnoreCase)))
{
if (entityType.GetCustomAttribute<SplitTableAttribute>() == null)
dbProvider.CodeFirst.InitTables(entityType);
else
dbProvider.CodeFirst.SplitTables().InitTables(entityType);
}
}
//第一次初始化数据 seed
if (tables.Count < 1)
UserDataSeed.InitData(db);
}
#endregion
}
}

277
API/Wood.Data.Repository/Extension/DatabaseExtension.cs

@ -0,0 +1,277 @@
using Serilog;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
using Wood.Util;
namespace Wood.Data.Repository
{
public static class DatabasesExtension
{
/// <summary>
/// 将DataReader数据转为Dynamic对象
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static dynamic DataFillDynamic(IDataReader reader)
{
using (reader)
{
dynamic d = new ExpandoObject();
for (int i = 0; i < reader.FieldCount; i++)
{
try
{
((IDictionary<string, object?>)d).Add(reader.GetName(i), reader.GetValue(i));
}
catch
{
((IDictionary<string, object?>)d).Add(reader.GetName(i), null);
}
}
return d;
}
}
/// <summary>
/// 获取模型对象集合
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static List<dynamic> DataFillDynamicList(IDataReader reader)
{
using (reader)
{
List<dynamic> list = new List<dynamic>();
if (reader != null && !reader.IsClosed)
{
while (reader.Read())
{
list.Add(DataFillDynamic(reader));
}
reader.Close();
reader.Dispose();
}
return list;
}
}
/// <summary>
/// 将IDataReader转换为集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reader"></param>
/// <returns></returns>
public static List<T> IDataReaderToList<T>(IDataReader reader)
{
using (reader)
{
List<string> field = new List<string>(reader.FieldCount);
for (int i = 0; i < reader.FieldCount; i++)
{
field.Add(reader.GetName(i).ToLower());
}
List<T> list = new List<T>();
while (reader.Read())
{
T model = Activator.CreateInstance<T>();
if (model != null)
{
var properties = ReflectionHelper.GetProperties(model.GetType());
if (properties != null)
{
foreach (PropertyInfo property in properties)
{
if (field.Contains(property.Name.ToLower()))
{
if (!IsNullOrDBNull(reader[property.Name]))
{
property.SetValue(model, HackType(reader[property.Name], property.PropertyType), null);
}
}
}
}
list.Add(model);
}
}
reader.Close();
reader.Dispose();
return list;
}
}
/// <summary>
/// 将IDataReader转换为DataTable
/// </summary>
/// <param name="dr"></param>
/// <returns></returns>
public static DataTable IDataReaderToDataTable(IDataReader reader)
{
using (reader)
{
DataTable objDataTable = new DataTable("Table");
int intFieldCount = reader.FieldCount;
for (int intCounter = 0; intCounter < intFieldCount; ++intCounter)
{
objDataTable.Columns.Add(reader.GetName(intCounter).ToLower(), reader.GetFieldType(intCounter));
}
objDataTable.BeginLoadData();
object[] objValues = new object[intFieldCount];
while (reader.Read())
{
reader.GetValues(objValues);
objDataTable.LoadDataRow(objValues, true);
}
reader.Close();
reader.Dispose();
objDataTable.EndLoadData();
return objDataTable;
}
}
/// <summary>
/// 获取实体类键值(缓存)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public static Hashtable GetPropertyInfo<T>(T entity)
{
Hashtable ht = new Hashtable();
PropertyInfo[]? props = ReflectionHelper.GetProperties(entity!.GetType());
if (props != null)
{
foreach (PropertyInfo prop in props)
{
bool flag = true;
foreach (Attribute attr in prop.GetCustomAttributes(true))
{
NotMappedAttribute? notMapped = attr as NotMappedAttribute;
if (notMapped != null)
{
flag = false;
break;
}
}
if (flag)
{
string name = prop.Name;
object? value = prop?.GetValue(entity, null);
ht[name] = value;
}
}
}
return ht;
}
public static IQueryable<T> AppendSort<T>(IQueryable<T> tempData, string sort, bool isAsc)
{
string[] sortArr = sort.Split(',');
MethodCallExpression? resultExpression = null;
for (int index = 0; index < sortArr.Length; index++)
{
string[] oneSortArr = sortArr[index].Trim().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
string sortField = oneSortArr[0];
bool sortAsc = isAsc;
if (oneSortArr.Length == 2)
{
sortAsc = string.Equals(oneSortArr[1], "asc", StringComparison.OrdinalIgnoreCase) ? true : false;
}
var parameter = Expression.Parameter(typeof(T), "t");
var property = ReflectionHelper.GetProperties(typeof(T))!.Where(p => p.Name.ToLower() == sortField.ToLower()).FirstOrDefault();
var propertyAccess = Expression.MakeMemberAccess(parameter, property!);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
if (index == 0)
{
resultExpression = Expression.Call(typeof(Queryable), sortAsc ? "OrderBy" : "OrderByDescending", new Type[] { typeof(T), property!.PropertyType }, tempData.Expression, Expression.Quote(orderByExpression));
}
else
{
resultExpression = Expression.Call(typeof(Queryable), sortAsc ? "ThenBy" : "ThenByDescending", new Type[] { typeof(T), property!.PropertyType }, tempData.Expression, Expression.Quote(orderByExpression));
}
tempData = tempData.Provider.CreateQuery<T>(resultExpression);
}
return tempData;
}
//这个类对可空类型进行判断转换,要不然会报错
public static object? HackType(object value, Type conversionType)
{
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null)
return null;
NullableConverter nullableConverter = new NullableConverter(conversionType);
conversionType = nullableConverter.UnderlyingType;
}
return Convert.ChangeType(value, conversionType);
}
public static bool IsNullOrDBNull(object obj)
{
return ((obj is DBNull) || string.IsNullOrEmpty(obj.ToString())) ? true : false;
}
/// <summary>
/// 获取使用Linq生成的Sql
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="query"></param>
/// <returns></returns>
//public static string GetSql<TEntity>(this IQueryable<TEntity> query)
//{
// var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
// var relationalCommandCache = enumerator.Private("_relationalCommandCache");
// var selectExpression = relationalCommandCache.Private<SelectExpression>("_selectExpression");
// var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");
// var sqlGenerator = factory.Create();
// var command = sqlGenerator.GetCommand(selectExpression);
// string sql = command.CommandText;
// return sql;
//}
/// <summary>
/// 获取运行时的Sql
/// </summary>
/// <param name="dbCommand"></param>
/// <returns></returns>
public static string GetCommandText(this DbCommand dbCommand)
{
var sql = dbCommand.CommandText;
foreach (DbParameter parameter in dbCommand.Parameters)
{
try
{
string? value = string.Empty;
switch (parameter.DbType)
{
case DbType.Date:
value = parameter.Value?.ToString()?.ToDateTime()?.ToString("yyyy-MM-dd HH:mm:ss");
break;
default:
value = parameter.Value?.ToString();
break;
}
sql = sql.Replace(parameter.ParameterName, value);
}
catch (Exception ex)
{
Log.Error(ex, "获取SQL语句时,组装sqlparameter参数失败:sql({sql}),DbType({DbType}),ParameterName({ParameterName}),ParameterValue({ParameterValue})",sql,parameter.DbType.ToString(), parameter.ParameterName, parameter.Value?.ToString());
}
}
return sql;
}
#region 私有方法
private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)!;
private static T Private<T>(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)!;
#endregion
}
}

110
API/Wood.Data.Repository/Extension/DatabasePageExtension.cs

@ -0,0 +1,110 @@
using System;
using System.Text;
using System.Data.Common;
using Wood.Util;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
namespace Wood.Data.Repository
{
public class DatabasePageExtension
{
public static StringBuilder SqlServerPageSql(string strSql, string sort, int pageSize, int pageIndex)
{
CheckSqlParam(sort);
StringBuilder sb = new StringBuilder();
if (pageIndex == 0)
{
pageIndex = 1;
}
int startNum = (pageIndex - 1) * pageSize;
int endNum = (pageIndex) * pageSize;
string orderBy = string.Empty;
if (!string.IsNullOrEmpty(sort))
{
orderBy = " ORDER BY " + sort;
}
else
{
orderBy = "ORDERE BY (SELECT 0)";
}
sb.Append("SELECT * FROM (SELECT ROW_NUMBER() Over (" + orderBy + ")");
sb.Append(" AS ROWNUM, * From (" + strSql + ") t ) AS N WHERE ROWNUM > " + startNum + " AND ROWNUM <= " + endNum + "");
return sb;
}
public static StringBuilder OraclePageSql(string strSql, string sort, int pageSize, int pageIndex)
{
CheckSqlParam(sort);
StringBuilder sb = new StringBuilder();
if (pageIndex == 0)
{
pageIndex = 1;
}
int startNum = (pageIndex - 1) * pageSize;
int endNum = (pageIndex) * pageSize;
string orderBy = string.Empty;
if (!string.IsNullOrEmpty(sort))
{
orderBy = " ORDER BY " + sort;
}
sb.Append("SELECT * From (SELECT ROWNUM AS n,");
sb.Append(" T.* From (" + strSql + orderBy + ") t ) N WHERE n > " + startNum + " AND n <= " + endNum + "");
return sb;
}
public static StringBuilder MySqlPageSql(string strSql, string sort, int pageSize, int pageIndex)
{
CheckSqlParam(sort);
StringBuilder sb = new StringBuilder();
if (pageIndex == 0)
{
pageIndex = 1;
}
int num = (pageIndex - 1) * pageSize;
string orderBy = string.Empty;
if (!string.IsNullOrEmpty(sort))
{
orderBy = " ORDER BY " + sort;
}
sb.Append(strSql + orderBy);
sb.Append(" LIMIT " + num + "," + pageSize + "");
return sb;
}
public static string GetCountSql(string strSql)
{
string countSql = string.Empty;
string strSqlCopy = strSql.ToLower();
int selectIndex = strSqlCopy.IndexOf("SELECT ");
int lastFromIndex = strSqlCopy.LastIndexOf(" FROM ");
if (selectIndex >= 0 && lastFromIndex >= 0)
{
int backFromIndex = strSqlCopy.LastIndexOf(" FROM ", lastFromIndex);
int backSelectIndex = strSqlCopy.LastIndexOf("SELECT ", lastFromIndex);
if (backSelectIndex == selectIndex)
{
countSql = "SELECT COUNT(*) " + strSql.Substring(lastFromIndex);
return countSql;
}
}
countSql = "SELECT COUNT(1) FROM (" + strSql + ") t";
return countSql;
}
private static void CheckSqlParam(string param)
{
if (!Regex.IsMatch(param, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|%|@|\*|!|\']"))
{
throw new ArgumentException("含有Sql注入的参数");
}
}
}
}

169
API/Wood.Data.Repository/Extension/RepositoryExtension.cs

@ -0,0 +1,169 @@
using SqlSugar;
using System.Linq.Expressions;
using System.Reflection;
using Wood.Entity;
using Wood.Util;
namespace Wood.Data.Repository
{
public static class RepositoryExtension
{
#region 过滤器清除
/// <summary>
/// 清除delete 过滤器
/// </summary>
/// <returns>ISugarQueryable<T></returns>
public static ISugarQueryable<T> ClearDeleteFilter<T>(this SimpleClient<T> repository) where T : EntityBase, new()
{
return repository.AsQueryable().ClearFilter<IDeletedFilter>();
}
/// <summary>
/// 清除 数据范围 过滤器
/// </summary>
/// <returns>ISugarQueryable<T></returns>
public static ISugarQueryable<T> ClearDataScopeFilter<T>(this SimpleClient<T> repository) where T : EntityBase, new()
{
return repository.AsQueryable().ClearFilter<IOrgIdFilter, ICreateUserIdFilter>();
}
/// <summary>
/// 设置自定义 status 过滤器
/// </summary>
/// <returns>ISugarQueryable<T></returns>
public static ISugarQueryable<T> AddStatusFilter<T>(this SimpleClient<T> repository, int status = 1) where T : EntityBaseExtra, new()
{
var query = repository.AsQueryable();
return query.Where(it => status == it.Status);
}
/// <summary>
/// 设置自定义 status 过滤器
/// </summary>
/// <returns>ISugarQueryable<T></returns>
public static ISugarQueryable<T> AddStatusFilter<T>(this SimpleClient<T> repository, params int[] status) where T : EntityBaseExtra, new()
{
var query = repository.AsQueryable();
return query.Where(it => status.Contains(it.Status));
}
#endregion
/// <summary>
/// 实体假删除异步 _rep.FakeDeleteAsync(entity)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="repository"></param>
/// <param name="entity">要删除的实体</param>
/// <returns></returns>
public static Task<int> FakeDeleteAsync<T>(this SimpleClient<T> repository, T entity) where T : EntityBase, new()
{
entity.IsDelete = true;
return repository.Context.Updateable(entity).UpdateColumns(it => new { it.IsDelete, it.UpdateTime, it.UpdateUserId }).ExecuteCommandAsync();
}
/// <summary>
/// 实体假删除 db.FakeDelete(entity)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="repository"></param>
/// <param name="whereExpression"></param>
/// <returns></returns>
public static Task<int> FakeDeleteAsync<T>(this SimpleClient<T> repository, Expression<Func<T, bool>> whereExpression) where T : EntityBase, new()
{
long? userId = GlobalContext.UserInfo?.UserId;
return repository.Context.Updateable<T>()
.AS()
.SetColumns("IsDelete", true)
.SetColumns("UpdateUserId", userId)
.SetColumns("UpdateTime", DateTime.Now)
.Where(whereExpression)
.ExecuteCommandAsync();
}
/// <summary>
/// 实体假删除 db.FakeDelete(entity)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="db"></param>
/// <param name="entity"></param>
/// <returns></returns>
public static Task<int> FakeDeleteAsync<T>(this SimpleClient<T> repository, List<T> entity) where T : EntityBase, new()
{
foreach (var item in entity)
item.IsDelete = true;
return repository.Context.Updateable(entity).UpdateColumns(it => new { it.IsDelete, it.UpdateTime, it.UpdateUserId }).ExecuteCommandAsync();
}
/// <summary>
/// 根据表名查询
/// </summary>
/// <param name="queryable"></param>
/// <returns> </returns>
public static ISugarQueryable<T> AS<T>(this ISugarQueryable<T> queryable)
{
var info = GetTableInfo<T>();
return queryable.AS<T>($"{info}");
}
/// <summary>
/// 根据表名查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <param name="queryable"></param>
/// <returns></returns>
public static ISugarQueryable<T, T2> AS<T, T2>(this ISugarQueryable<T, T2> queryable)
{
var info = GetTableInfo<T2>();
return queryable.AS<T2>($"{info}");
}
/// <summary>
/// 根据表名更新
/// </summary>
/// <param name="updateable"></param>
/// <returns> </returns>
public static IUpdateable<T> AS<T>(this IUpdateable<T> updateable) where T : EntityBase, new()
{
var info = GetTableInfo<T>();
return updateable.AS($"{info}");
}
/// <summary>
/// 根据表名新增
/// </summary>
/// <param name="insertable"></param>
/// <returns> </returns>
public static IInsertable<T> AS<T>(this IInsertable<T> insertable) where T : EntityBase, new()
{
var info = GetTableInfo<T>();
return insertable.AS($"{info}");
}
/// <summary>
/// 根据表名删除
/// </summary>
/// <param name="deleteable"></param>
/// <returns> </returns>
public static IDeleteable<T> AS<T>(this IDeleteable<T> deleteable) where T : EntityBase, new()
{
var info = GetTableInfo<T>();
return deleteable.AS($"{info}");
}
/// <summary>
/// 根据实体类型获取表信息
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static string? GetTableInfo<T>()
{
var entityType = typeof(T);
var tableName = entityType.GetCustomAttribute<SugarTable>()?.TableName;
return tableName;
}
}
}

146
API/Wood.Data.Repository/Extension/SqlSugarPagedExtensions.cs

@ -0,0 +1,146 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Wood.Entity;
namespace Wood.Data.Repository
{
/// <summary>
/// 分页拓展类
/// </summary>
public static class SqlSugarPagedExtensions
{
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <param name="expression">查询结果 Select 表达式</param>
/// <returns></returns>
public static TDataPaged<TResult> ToPagedList<TEntity, TResult>(this ISugarQueryable<TEntity> query, int pageIndex, int pageSize,
Expression<Func<TEntity, TResult>> expression)
{
var total = 0;
var items = query.ToPageList(pageIndex, pageSize, ref total, expression);
return CreateSqlSugarPagedList(items, total, pageIndex, pageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <returns></returns>
public static TDataPaged<TEntity> ToPagedList<TEntity>(this ISugarQueryable<TEntity> query, int pageIndex, int pageSize)
{
var total = 0;
var items = query.ToPageList(pageIndex, pageSize, ref total);
return CreateSqlSugarPagedList(items, total, pageIndex, pageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <param name="expression">查询结果 Select 表达式</param>
/// <returns></returns>
public static async Task<TDataPaged<TResult>> ToPagedListAsync<TEntity, TResult>(this ISugarQueryable<TEntity> query, int pageIndex, int pageSize,
Expression<Func<TEntity, TResult>> expression)
{
RefAsync<int> total = 0;
var items = await query.ToPageListAsync(pageIndex, pageSize, total, expression);
return CreateSqlSugarPagedList(items, total, pageIndex, pageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <returns></returns>
public static async Task<TDataPaged<TEntity>> ToPagedListAsync<TEntity>(this ISugarQueryable<TEntity> query, int pageIndex, int pageSize)
{
RefAsync<int> total = 0;
var items = await query.ToPageListAsync(pageIndex, pageSize, total);
return CreateSqlSugarPagedList(items, total, pageIndex, pageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <param name="expression">查询结果 Select 表达式</param>
/// <returns></returns>
public static async Task<TDataPaged<TResult>> ToPagedListAsync<TEntity, TResult>(this ISugarQueryable<TEntity> query, Pagination pagination,
Expression<Func<TEntity, TResult>> expression)
{
RefAsync<int> total = 0;
var items = await query.OrderBy(pagination.Sort).ToPageListAsync(pagination.PageIndex, pagination.PageSize, total, expression);
return CreateSqlSugarPagedList(items, total, pagination.PageIndex, pagination.PageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="query"><see cref="ISugarQueryable{TEntity}"/>对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <returns></returns>
public static async Task<TDataPaged<TEntity>> ToPagedListAsync<TEntity>(this ISugarQueryable<TEntity> query, Pagination pagination)
{
RefAsync<int> total = 0;
var items = await query.OrderBy(pagination.Sort).ToPageListAsync(pagination.PageIndex, pagination.PageSize, total);
return CreateSqlSugarPagedList(items, total, pagination.PageIndex, pagination.PageSize);
}
/// <summary>
/// 分页拓展
/// </summary>
/// <param name="list">集合对象</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <returns></returns>
public static TDataPaged<TEntity> ToPagedList<TEntity>(this IEnumerable<TEntity> list, int pageIndex, int pageSize)
{
var total = list.Count();
var items = list.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return CreateSqlSugarPagedList(items, total, pageIndex, pageSize);
}
/// <summary>
/// 创建 <see cref="SqlSugarPagedList{TEntity}"/> 对象
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="items">分页内容的对象集合</param>
/// <param name="total">总条数</param>
/// <param name="pageIndex">当前页码,从1开始</param>
/// <param name="pageSize">页码容量</param>
/// <returns></returns>
public static TDataPaged<TEntity> CreateSqlSugarPagedList<TEntity>(IEnumerable<TEntity> items, int total, int pageIndex, int pageSize)
{
var totalPages = pageSize > 0 ? (int)Math.Ceiling(total / (double)pageSize) : 0;
return new TDataPaged<TEntity>
{
Page = pageIndex,
PageSize = pageSize,
Data = items,
Total = total,
TotalPages = totalPages,
HasNextPage = pageIndex < totalPages,
HasPrevPage = pageIndex - 1 > 0
};
}
}
}

92
API/Wood.Data.Repository/Repository.cs

@ -0,0 +1,92 @@
using SqlSugar;
using System.Data;
using System.Data.Common;
using System.Text;
using Wood.Entity;
using Wood.Util;
namespace Wood.Data.Repository
{
/// <summary>
/// 创建人:admin
/// 日 期:2018.10.18
/// 描 述:定义仓储模型中的数据标准操作接口
/// </summary>
public class SqlSugarRepository<T> : SimpleClient<T> where T : class, new()
{
#region 构造函数
public SqlSugarRepository(ISqlSugarClient sqlSugarClient)
{
base.Context = sqlSugarClient;
}
#endregion
#region 执行 SQL 语句
public async Task<int> ExecuteBySql(string strSql)
{
return await Context.Ado.ExecuteCommandAsync(strSql);
}
public async Task<int> ExecuteBySql(string strSql, params DbParameter[] dbParameter)
{
return await Context.Ado.ExecuteCommandAsync(strSql, dbParameter);
}
public async Task<int> ExecuteByProc(string procName)
{
return await Context.Ado.UseStoredProcedure().ExecuteCommandAsync(procName);
}
public async Task<int> ExecuteByProc(string procName, params DbParameter[] dbParameter)
{
return await Context.Ado.UseStoredProcedure().ExecuteCommandAsync(procName, dbParameter);
}
#endregion
#region 数据源 查询
public async Task<DataTable> FindTable(string strSql)
{
return await Context.Ado.GetDataTableAsync(strSql);
}
public async Task<DataTable> FindTable(string strSql, DbParameter[] dbParameter)
{
return await Context.Ado.GetDataTableAsync(strSql, dbParameter);
}
public async Task<DataTable> FindTable(string strSql, Pagination pagination)
{
var data = await FindTable(strSql, pagination.Sort, pagination.PageSize, pagination.PageIndex);
pagination.TotalCount = data.total;
return data.Item2;
}
public async Task<DataTable> FindTable(string strSql, DbParameter[] dbParameter, Pagination pagination)
{
var data = await FindTable(strSql, dbParameter, pagination.Sort, pagination.PageSize, pagination.PageIndex);
pagination.TotalCount = data.total;
return data.Item2;
}
private async Task<(int total, DataTable)> FindTable(string strSql, string sort, int pageSize, int pageIndex)
{
return await FindTable(strSql, null, sort, pageSize, pageIndex);
}
private async Task<(int total, DataTable)> FindTable(string strSql, DbParameter[]? dbParameter, string sort, int pageSize, int pageIndex)
{
StringBuilder sb = new StringBuilder();
if (Context.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySql)
sb.Append(DatabasePageExtension.MySqlPageSql(strSql, sort, pageSize, pageIndex));
else if (Context.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
sb.Append(DatabasePageExtension.OraclePageSql(strSql, sort, pageSize, pageIndex));
else if (Context.CurrentConnectionConfig.DbType == SqlSugar.DbType.SqlServer)
sb.Append(DatabasePageExtension.SqlServerPageSql(strSql, sort, pageSize, pageIndex));
else
sb.Append(DatabasePageExtension.MySqlPageSql(strSql, sort, pageSize, pageIndex));
object tempTotal = await Context.Ado.ExecuteCommandAsync("SELECT COUNT(1) FROM (" + strSql + ") T", dbParameter);
int total = tempTotal?.ToString()?.ToInt()??0;
if (total > 0)
{
var table = await Context.Ado.GetDataTableAsync(sb.ToString(), dbParameter);
return (total, table);
}
else
return (total, new DataTable());
}
#endregion
}
}

35
API/Wood.Data.Repository/UnitOfWork/IUnitOfWork.cs

@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wood.Data.Repository
{
/// <summary>
/// 工作单元依赖接口
/// </summary>
public interface IUnitOfWork
{
/// <summary>
/// 开启工作单元处理
/// </summary>
void BeginTransaction();
/// <summary>
/// 提交工作单元处理
/// </summary>
void CommitTransaction();
/// <summary>
/// 回滚工作单元处理
/// </summary>
void RollbackTransaction();
/// <summary>
/// 执行完毕(无论成功失败)
/// </summary>
void OnCompleted();
}
}

79
API/Wood.Data.Repository/UnitOfWork/SqlSugarUnitOfWork.cs

@ -0,0 +1,79 @@
// 麻省理工学院许可证
//
// 版权所有 (c) 2021-2023 zuohuaijun,大名科技(天津)有限公司 联系电话/微信:18020030720 QQ:515096995
//
// 特此免费授予获得本软件的任何人以处理本软件的权利,但须遵守以下条件:在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
//
// 软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性和非侵权的保证。
// 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是因合同、侵权或其他方式引起的,与软件或其使用或其他交易有关。
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System.Reflection;
using System.Transactions;
namespace Wood.Data.Repository;
/// <summary>
/// SqlSugar 事务和工作单元
/// </summary>
public sealed class SqlSugarUnitOfWork : IUnitOfWork
{
/// <summary>
/// SqlSugar 对象
/// </summary>
private readonly ISqlSugarClient _sqlSugarClient;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="sqlSugarClient"></param>
public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)
{
_sqlSugarClient = sqlSugarClient;
}
/// <summary>
/// 开启工作单元处理
/// </summary>
/// <param name="context"></param>
/// <param name="unitOfWork"></param>
public void BeginTransaction()
{
_sqlSugarClient.AsTenant().BeginTran();
}
/// <summary>
/// 提交工作单元处理
/// </summary>
/// <param name="resultContext"></param>
/// <param name="unitOfWork"></param>
public void CommitTransaction()
{
_sqlSugarClient.AsTenant().CommitTran();
}
/// <summary>
/// 回滚工作单元处理
/// </summary>
/// <param name="resultContext"></param>
/// <param name="unitOfWork"></param>
public void RollbackTransaction()
{
_sqlSugarClient.AsTenant().RollbackTran();
}
/// <summary>
/// 执行完毕(无论成功失败)
/// </summary>
/// <param name="context"></param>
/// <param name="resultContext"></param>
public void OnCompleted()
{
_sqlSugarClient.Dispose();
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save