加入任务调度模块

This commit is contained in:
橙子
2021-10-30 18:48:58 +08:00
parent ec5982a6e3
commit 35f39eb65b
30 changed files with 1012 additions and 46 deletions

View File

@@ -152,5 +152,6 @@ namespace Yi.Framework.ApiMicroservice.Controllers
return Result.Success(msg);
}
}
}

View File

@@ -0,0 +1,70 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common;
using Yi.Framework.Common.Helper;
using Yi.Framework.Common.Models;
using Yi.Framework.Core;
using Yi.Framework.DTOModel;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
namespace Yi.Framework.ApiMicroservice.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class JobController : Controller
{
private readonly ILogger<JobController> _logger;
private QuartzInvoker _quartzInvoker;
public JobController(ILogger<JobController> logger,QuartzInvoker quartzInvoker)
{
_logger = logger;
_quartzInvoker = quartzInvoker;
}
[HttpPost]
public async Task<Result> startJob()
{
await _quartzInvoker.start("*/1 * * * * ? ", new Quartz.JobKey("test", "my"), "VisitJob");
return Result.Success();
}
[HttpGet]
public async Task<Result> getRunJobList()
{
return Result.Success().SetData(await _quartzInvoker.getRunJobList());
}
[HttpGet]
public Result getJobClass()
{
return Result.Success().SetData(_quartzInvoker.getJobClassList());
}
[HttpPut]
public async Task<Result> stopJob()
{
await _quartzInvoker.Stop(new Quartz.JobKey("test", "my"));
return Result.Success();
}
[HttpDelete]
public async Task<Result> DeleteJob()
{
await _quartzInvoker.Delete(new Quartz.JobKey("test", "my"));
return Result.Success();
}
[HttpPut]
public async Task<Result> ResumeJob()
{
await _quartzInvoker.Resume(new Quartz.JobKey("test", "my"));
return Result.Success();
}
}
}

View File

@@ -27,6 +27,11 @@ namespace Yi.Framework.ApiMicroservice
#endregion
services.AddIocService(Configuration);
#region
//Quartz<74><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion
services.AddQuartzService();
#region
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<2B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion

View File

@@ -39,6 +39,12 @@
<param name="pwdDto"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.GetMenuInMould">
<summary>
这个是要递归的,但是要过滤掉删除的,所以,可以写一个通用过滤掉删除的方法
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.UpdateMenu(Yi.Framework.Model.Models.menu)">
<summary>
@@ -53,9 +59,10 @@
<param name="_ids"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.AddMenu(Yi.Framework.Model.Models.menu)">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.AddTopMenu(Yi.Framework.Model.Models.menu)">
<summary>
现在top菜单只允许为一个
</summary>
<param name="_menu"></param>
<returns></returns>
@@ -63,16 +70,11 @@
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.SetMouldByMenu(Yi.Framework.DTOModel.IdDto{System.Int32})">
<summary>
给一个菜单设置一个接口,Id1为菜单id,Id2为接口id
用于给菜单设置接口
</summary>
<param name="idDto"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.GetMenuByUser">
<summary>
得到该用户有哪些菜单关联mould
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.AddChildrenMenu(Yi.Framework.DTOModel.ChildrenDto{Yi.Framework.Model.Models.menu})">
<summary>
给一个菜单添加子节点(注意:添加,不是覆盖)
@@ -80,9 +82,10 @@
<param name="childrenDto"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.GeTopMenuByUser">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.MenuController.GetTopMenusByHttpUser">
<summary>
获取用户的目录菜单,不包含接口
用于账户信息页面,显示这个用户有哪些菜单,需要并列
</summary>
<returns></returns>
</member>
@@ -128,13 +131,28 @@
<param name="_role"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.RoleController.GetRolesByUserId(System.Int32)">
<summary>
根据用户id得到该用户有哪些角色
用于显示用户详情中的角色说明
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.RoleController.SetMenuByRole(Yi.Framework.DTOModel.IdsListDto{System.Int32})">
<summary>
给角色设置菜单多个角色与多个菜单让每一个角色都设置ids1为角色ids2为菜单
用于设置角色
</summary>
<param name="idsListDto"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.RoleController.GetTopMenusByRoleId(System.Int32)">
<summary>
用于给角色设置菜单的时候,点击一个角色,显示这个角色拥有的并列的菜单
</summary>
<param name="roleId"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetUser">
<summary>
@@ -162,36 +180,34 @@
<param name="_user"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetMenuMould">
<summary>
通过上下文对象获取user注意_user下只有userId返回值为该用户下所有的menu(注意子类递归)并且需要关联mould
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.SetRoleByUser(Yi.Framework.DTOModel.IdsListDto{System.Int32})">
<summary>
给多个用户设置多个角色ids有用户id与 角色列表ids多对多,ids1用户,ids2为角色
用户设置给用户设置角色
</summary>
<param name="idsListDto"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetRolesByUser">
<summary>
根据http上下文的用户得到该用户有哪些角色
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetRolesByUserId(System.Int32)">
<summary>
根据用户id得到该用户有哪些角色
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetUserInfoById">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetUserInRolesByHttpUser">
<summary>
根据http上下文的用户得到该用户信息关联角色
用于显示账号信息页中的用户信息和角色信息
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetMenuByHttpUser">
<summary>
得到登录用户的递归菜单,放到导航栏
用户放到导航栏中
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.UserController.GetAxiosByRouter(System.String)">
<summary>
得到请求模型
</summary>
<param name="router"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@@ -14,7 +14,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Quartz" Version="3.3.3" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,5 +1,4 @@
{
"urls": "http://*:19000",
"Logging": {
"LogLevel": {
"Default": "Information",

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Common.Helper
{
public class AssemblyHelper
{
public static List<Type> GetClass(string assemblyFile, string className = null, string spaceName=null)
{
Assembly assembly = Assembly.Load(assemblyFile);
return assembly.GetTypes().Where(m => m.IsClass
&& m.Name==null?true:m.Name==className
).ToList();
}
}
}

View File

@@ -4,9 +4,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.TaskJob
namespace Yi.Framework.Common.Models
{
class VisitJob
public class visitModel
{
public static int visitNum { get; set; } = 0;
}
}

View File

@@ -0,0 +1,32 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Core.Quartz
{
public class MyQuartzFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public MyQuartzFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
disposable?.Dispose();
}
}
}

View File

@@ -0,0 +1,144 @@
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl.Matchers;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Helper;
using Yi.Framework.Job;
namespace Yi.Framework.Core
{
public class QuartzInvoker
{
private readonly ISchedulerFactory _schedulerFactory;
private IScheduler _scheduler;
private ILogger<QuartzInvoker> _logger;
private IJobFactory _jobFactory;
public QuartzInvoker(ISchedulerFactory schedulerFactory, ILogger<QuartzInvoker> logger, IJobFactory jobFactory)
{
_schedulerFactory = schedulerFactory;
_logger = logger;
_jobFactory = jobFactory;
}
/// <summary>
/// 开始任务
/// </summary>
/// <param name="cron"></param>
/// <param name="jobKey"></param>
/// <param name="jobClass"></param>
/// <param name="second"></param>
/// <param name="data"></param>
/// <returns></returns>
public async Task start(string cron, JobKey jobKey, string jobClass, long second = 0)
{
var myClass = AssemblyHelper.GetClass("Yi.Framework.Job", jobClass).FirstOrDefault();
_scheduler = await _schedulerFactory.GetScheduler();
_scheduler.JobFactory = _jobFactory;
//开启调度器
await _scheduler.Start();
//创建一个触发器
var trigger = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddSeconds(second))
.WithCronSchedule(cron)
.Build();
//创建任务
var jobDetail = JobBuilder.Create(myClass)
.WithIdentity(jobKey.Name, jobKey.Group)
.Build();
//将触发器和任务器绑定到调度器中
await _scheduler.ScheduleJob(jobDetail, trigger);
_logger.LogWarning($"开始任务:{jobKey.Name},组别:{jobKey.Group}");
}
/// <summary>
/// 暂停任务
/// </summary>
/// <param name="jobKey"></param>
/// <returns></returns>
public async Task Stop(JobKey jobKey)
{
var _scheduler = await _schedulerFactory.GetScheduler();
//LogUtil.Debug($"暂停任务{jobKey.Group},{jobKey.Name}");
await _scheduler.PauseJob(jobKey);
_logger.LogWarning($"暂停任务:{jobKey.Name},组别:{jobKey.Group}");
}
public async Task Delete(JobKey jobKey)
{
var _scheduler = await _schedulerFactory.GetScheduler();
//LogUtil.Debug($"暂停任务{jobKey.Group},{jobKey.Name}");
await _scheduler.DeleteJob(jobKey);
_logger.LogWarning($"删除任务:{jobKey.Name},组别:{jobKey.Group}");
}
public async Task Resume(JobKey jobKey)
{
var _scheduler = await _schedulerFactory.GetScheduler();
//LogUtil.Debug($"恢复任务{jobKey.Group},{jobKey.Name}");
await _scheduler.ResumeJob(jobKey);
_logger.LogWarning($"恢复任务:{jobKey.Name},组别:{jobKey.Group}");
}
/// <summary>
/// 得到可运行的job列表
/// </summary>
/// <returns></returns>
public List<string> getJobClassList()
{
var myClassList = AssemblyHelper.GetClass("Yi.Framework.Job");
List<string> data = new List<string>();
myClassList.ForEach(k => data.Add(k.Name));
return data;
}
/// <summary>
/// 得到现在正在运行的任务列表
/// </summary>
/// <returns></returns>
public async Task<List<JobKey>> getRunJobList()
{
_scheduler = await _schedulerFactory.GetScheduler();
var groups = await _scheduler.GetJobGroupNames();
var data = new List<JobKey>();
foreach (var groupName in groups)
{
foreach (var jobKey in await _scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)))
{
string jobName = jobKey.Name;
string jobGroup = jobKey.Group;
data.Add(jobKey);
var triggers = await _scheduler.GetTriggersOfJob(jobKey);
foreach (ITrigger trigger in triggers)
{
///下一次的执行时间
var utcTime =trigger.GetNextFireTimeUtc();
string str = utcTime.ToString();
//TimeZone.CurrentTimeZone.ToLocalTime(Convert.ToDateTime(str));
}
}
}
return data;
}
}
public class JobKeyModel
{
public JobKey jobKey { get; set; }
public DateTime? nextTime { get; set; }
}
}

View File

@@ -17,6 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\Yi.Framework.Common\Yi.Framework.Common.csproj" />
<ProjectReference Include="..\Yi.Framework.Model\Yi.Framework.Model.csproj" />
<ProjectReference Include="..\Yi.Framework.Task\Yi.Framework.Job.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -31,4 +31,10 @@ namespace Yi.Framework.Interface
Task<bool> DelListByUpdateAsync(List<int> _ids);
Task<IEnumerable<user>> GetAllEntitiesTrueAsync();
}
public partial interface IVisitService:IBaseService<visit>
{
Task<bool> DelListByUpdateAsync(List<int> _ids);
Task<IEnumerable<visit>> GetAllEntitiesTrueAsync();
}
}

View File

@@ -16,7 +16,7 @@ namespace Yi.Framework.Model
public partial class DataContext : DbContext
{
//private readonly IOptionsMonitor<MySqlConnOptions> _optionsMonitor;
private string _connStr;
public static string _connStr;
public static string DbSelect = DbConst.Mysql;
//public DataContext(IOptionsMonitor<MySqlConnOptions> optionsMonitor)
//{

View File

@@ -0,0 +1,199 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Yi.Framework.Model;
namespace Yi.Framework.Model.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20211030074708_yi-3")]
partial class yi3
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.11");
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("icon")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<int>("is_show")
.HasColumnType("int");
b.Property<int>("is_top")
.HasColumnType("int");
b.Property<string>("menu_name")
.HasColumnType("longtext");
b.Property<int?>("menuid")
.HasColumnType("int");
b.Property<int?>("mouldid")
.HasColumnType("int");
b.Property<int?>("roleid")
.HasColumnType("int");
b.Property<string>("router")
.HasColumnType("longtext");
b.Property<int>("sort")
.HasColumnType("int");
b.HasKey("id");
b.HasIndex("menuid");
b.HasIndex("mouldid");
b.HasIndex("roleid");
b.ToTable("menu");
});
modelBuilder.Entity("Yi.Framework.Model.Models.mould", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("mould_name")
.HasColumnType("longtext");
b.Property<string>("url")
.HasColumnType("longtext");
b.HasKey("id");
b.ToTable("mould");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("introduce")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("role_name")
.HasColumnType("longtext");
b.Property<int?>("userid")
.HasColumnType("int");
b.HasKey("id");
b.HasIndex("userid");
b.ToTable("role");
});
modelBuilder.Entity("Yi.Framework.Model.Models.user", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("address")
.HasColumnType("longtext");
b.Property<int?>("age")
.HasColumnType("int");
b.Property<string>("email")
.HasColumnType("longtext");
b.Property<string>("icon")
.HasColumnType("longtext");
b.Property<string>("introduction")
.HasColumnType("longtext");
b.Property<string>("ip")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("nick")
.HasColumnType("longtext");
b.Property<string>("password")
.HasColumnType("longtext");
b.Property<int?>("phone")
.HasColumnType("int");
b.Property<string>("username")
.HasColumnType("longtext");
b.HasKey("id");
b.ToTable("user");
});
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.HasOne("Yi.Framework.Model.Models.menu", null)
.WithMany("children")
.HasForeignKey("menuid");
b.HasOne("Yi.Framework.Model.Models.mould", "mould")
.WithMany()
.HasForeignKey("mouldid");
b.HasOne("Yi.Framework.Model.Models.role", null)
.WithMany("menus")
.HasForeignKey("roleid");
b.Navigation("mould");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.HasOne("Yi.Framework.Model.Models.user", null)
.WithMany("roles")
.HasForeignKey("userid");
});
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.Navigation("children");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.Navigation("menus");
});
modelBuilder.Entity("Yi.Framework.Model.Models.user", b =>
{
b.Navigation("roles");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Yi.Framework.Model.Migrations
{
public partial class yi3 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@@ -0,0 +1,219 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Yi.Framework.Model;
namespace Yi.Framework.Model.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20211030074922_yi-5")]
partial class yi5
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.11");
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("icon")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<int>("is_show")
.HasColumnType("int");
b.Property<int>("is_top")
.HasColumnType("int");
b.Property<string>("menu_name")
.HasColumnType("longtext");
b.Property<int?>("menuid")
.HasColumnType("int");
b.Property<int?>("mouldid")
.HasColumnType("int");
b.Property<int?>("roleid")
.HasColumnType("int");
b.Property<string>("router")
.HasColumnType("longtext");
b.Property<int>("sort")
.HasColumnType("int");
b.HasKey("id");
b.HasIndex("menuid");
b.HasIndex("mouldid");
b.HasIndex("roleid");
b.ToTable("menu");
});
modelBuilder.Entity("Yi.Framework.Model.Models.mould", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("mould_name")
.HasColumnType("longtext");
b.Property<string>("url")
.HasColumnType("longtext");
b.HasKey("id");
b.ToTable("mould");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("introduce")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("role_name")
.HasColumnType("longtext");
b.Property<int?>("userid")
.HasColumnType("int");
b.HasKey("id");
b.HasIndex("userid");
b.ToTable("role");
});
modelBuilder.Entity("Yi.Framework.Model.Models.user", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("address")
.HasColumnType("longtext");
b.Property<int?>("age")
.HasColumnType("int");
b.Property<string>("email")
.HasColumnType("longtext");
b.Property<string>("icon")
.HasColumnType("longtext");
b.Property<string>("introduction")
.HasColumnType("longtext");
b.Property<string>("ip")
.HasColumnType("longtext");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<string>("nick")
.HasColumnType("longtext");
b.Property<string>("password")
.HasColumnType("longtext");
b.Property<int?>("phone")
.HasColumnType("int");
b.Property<string>("username")
.HasColumnType("longtext");
b.HasKey("id");
b.ToTable("user");
});
modelBuilder.Entity("Yi.Framework.Model.Models.visit", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<int>("num")
.HasColumnType("int");
b.Property<DateTime>("time")
.HasColumnType("datetime(6)");
b.HasKey("id");
b.ToTable("visit");
});
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.HasOne("Yi.Framework.Model.Models.menu", null)
.WithMany("children")
.HasForeignKey("menuid");
b.HasOne("Yi.Framework.Model.Models.mould", "mould")
.WithMany()
.HasForeignKey("mouldid");
b.HasOne("Yi.Framework.Model.Models.role", null)
.WithMany("menus")
.HasForeignKey("roleid");
b.Navigation("mould");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.HasOne("Yi.Framework.Model.Models.user", null)
.WithMany("roles")
.HasForeignKey("userid");
});
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.Navigation("children");
});
modelBuilder.Entity("Yi.Framework.Model.Models.role", b =>
{
b.Navigation("menus");
});
modelBuilder.Entity("Yi.Framework.Model.Models.user", b =>
{
b.Navigation("roles");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Yi.Framework.Model.Migrations
{
public partial class yi5 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "visit",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
time = table.Column<DateTime>(type: "datetime(6)", nullable: false),
num = table.Column<int>(type: "int", nullable: false),
is_delete = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_visit", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "visit");
}
}
}

View File

@@ -153,6 +153,26 @@ namespace Yi.Framework.Model.Migrations
b.ToTable("user");
});
modelBuilder.Entity("Yi.Framework.Model.Models.visit", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("is_delete")
.HasColumnType("int");
b.Property<int>("num")
.HasColumnType("int");
b.Property<DateTime>("time")
.HasColumnType("datetime(6)");
b.HasKey("id");
b.ToTable("visit");
});
modelBuilder.Entity("Yi.Framework.Model.Models.menu", b =>
{
b.HasOne("Yi.Framework.Model.Models.menu", null)

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Model.Models
{
public class visit:baseModel<int>
{
public DateTime time { get; set; }
public int num { get; set; }
}
}

View File

@@ -12,6 +12,7 @@ namespace Yi.Framework.Model
public DbSet<mould> mould { get; set; }
public DbSet<role> role { get; set; }
public DbSet<user> user { get; set; }
public DbSet<visit> visit { get; set; }
}
}

View File

@@ -82,4 +82,22 @@ namespace Yi.Framework.Service
}
}
public partial class VisitService:BaseService<visit>,IVisitService
{
public VisitService(IDbContextFactory DbFactory):base(DbFactory){ }
public async Task<bool> DelListByUpdateAsync(List<int> _ids)
{
var visitList = await GetEntitiesAsync(u=>_ids.Contains(u.id));
visitList.ToList().ForEach(u => u.is_delete = (short)Common.Enum.DelFlagEnum.Deleted);
return await UpdateListAsync(visitList);
}
public async Task<IEnumerable<visit>> GetAllEntitiesTrueAsync()
{
return await GetEntitiesAsync(u=> u.is_delete == (short)Common.Enum.DelFlagEnum.Normal);
}
}
}

View File

@@ -0,0 +1,27 @@
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Job
{
public class HttpJob : IJob
{
private ILogger<VisitJob> _logger;
public HttpJob(ILogger<VisitJob> logger)
{
_logger = logger;
}
public Task Execute(IJobExecutionContext context)
{
return Task.Run(() =>
{
});
}
}
}

View File

@@ -0,0 +1,45 @@

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Model.ModelFactory;
using Yi.Framework.Model.Models;
namespace Yi.Framework.Job
{
public class VisitJob : IJob
{
private ILogger<VisitJob> _logger;
private DbContext _DBWrite;
public VisitJob(ILogger<VisitJob> logger, IDbContextFactory DbFactory)
{
_logger = logger;
_DBWrite = DbFactory.ConnWriteOrRead(Common.Enum.WriteAndReadEnum.Write);
}
/// <summary>
/// 应该将拜访清零,并且写入数据库中的拜访表中
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public Task Execute(IJobExecutionContext context)
{
return Task.Run(() =>
{
_DBWrite.Set<visit>().Add(new visit() { num = visitModel.visitNum, time = DateTime.Now });
_DBWrite.SaveChanges();
_logger.LogWarning("定时任务开始调度:" + nameof(VisitJob) + ":" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + $":访问总数为:{visitModel.visitNum}");
visitModel.visitNum = 0;
}
);
}
}
}

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quartz.AspNetCore" Version="3.3.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Yi.Framework.Common\Yi.Framework.Common.csproj" />
<ProjectReference Include="..\Yi.Framework.Model\Yi.Framework.Model.csproj" />
</ItemGroup>
</Project>

View File

@@ -15,7 +15,6 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
if (Appsettings.appBool("Cors_Enabled"))
{
services.AddCors(options => options.AddPolicy("CorsPolicy",//解决跨域问题
builder =>
{

View File

@@ -16,6 +16,7 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
{
DbContextFactory.MutiDB_Enabled = Appsettings.appBool("MutiDB_Enabled");
DataContext.DbSelect = Appsettings.app("DbSelect");
DataContext._connStr = Appsettings.app("DbConn", "WriteUrl");
services.Configure<DbConnOptions>(Appsettings.appConfiguration("DbConn"));
return services;
}

View File

@@ -0,0 +1,34 @@
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Core;
using Yi.Framework.Core.Quartz;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 启动定时器服务,后台服务
/// </summary>
public static class QuartzExtensions
{
/// <summary>
/// 使用定时器
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddQuartzService(this IServiceCollection services)
{
services.AddSingleton<QuartzInvoker>();
services.AddSingleton<IJobFactory, MyQuartzFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
return services;
}
}
}

View File

@@ -10,6 +10,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Yi.Framework.Job;
using Yi.Framework.Model.ModelFactory;
using Yi.Framework.WebCore.Utility;
using Module = Autofac.Module;
@@ -18,26 +19,44 @@ namespace Yi.Framework.WebCore.Utility
{
public class CustomAutofacModule : Module
{
protected override void Load(ContainerBuilder containerBuilder)
private Assembly GetDll(string ass)
{
containerBuilder.RegisterType<DbContextFactory>().As<IDbContextFactory>().InstancePerDependency().EnableInterfaceInterceptors();
var basePath = AppContext.BaseDirectory;
var servicesDllFile = Path.Combine(basePath, "Yi.Framework.Service.dll");
var servicesDllFile = Path.Combine(basePath, ass);
if (!(File.Exists(servicesDllFile)))
{
var msg = "service.dll 丢失,请编译后重新生成。";
throw new Exception(msg);
}
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
return Assembly.LoadFrom(servicesDllFile); ;
}
protected override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<DbContextFactory>().As<IDbContextFactory>().InstancePerDependency().EnableInterfaceInterceptors();
///反射注入服务层及接口层
var assemblysServices = GetDll( "Yi.Framework.Service.dll");
containerBuilder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerDependency()
.EnableInterfaceInterceptors();
///反射注册任务调度层
var assemblysJob = GetDll("Yi.Framework.Job.dll");
containerBuilder.RegisterAssemblyTypes(assemblysJob)
.InstancePerDependency();
containerBuilder.Register(c => new CustomAutofacAop());//AOP注册
//containerBuilder.RegisterType<A>().As<IA>().EnableInterfaceInterceptors();开启Aop
//将数据库对象注入

View File

@@ -15,6 +15,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="5.0.4" />
<PackageReference Include="Quartz.AspNetCore" Version="3.3.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
</ItemGroup>

View File

@@ -29,17 +29,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.WebCore", "Yi.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ApiMicroservice", "Yi.Framework.ApiMicroservice\Yi.Framework.ApiMicroservice.csproj", "{A95157D2-907F-411E-BA1D-A17F48C54A0E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.OcelotGateway", "Yi.Framework.OcelotGateway\Yi.Framework.OcelotGateway.csproj", "{671E38D8-ECAF-484B-A2AE-63DDC469C315}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.OcelotGateway", "Yi.Framework.OcelotGateway\Yi.Framework.OcelotGateway.csproj", "{671E38D8-ECAF-484B-A2AE-63DDC469C315}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AuthenticationCenter", "Yi.Framework.AuthenticationCenter\Yi.Framework.AuthenticationCenter.csproj", "{694C0EC0-ED32-4E5D-8EA1-FB82E1303EAB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuthenticationCenter", "Yi.Framework.AuthenticationCenter\Yi.Framework.AuthenticationCenter.csproj", "{694C0EC0-ED32-4E5D-8EA1-FB82E1303EAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.StaticPageProcessor", "Yi.Framework.StaticPageProcessor\Yi.Framework.StaticPageProcessor.csproj", "{D2BC3EBE-7F08-476E-9BB5-58A6F27AB31A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.StaticPageProcessor", "Yi.Framework.StaticPageProcessor\Yi.Framework.StaticPageProcessor.csproj", "{D2BC3EBE-7F08-476E-9BB5-58A6F27AB31A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.ElasticSearchProcessor", "Yi.Framework.ElasticSearchProcessor\Yi.Framework.ElasticSearchProcessor.csproj", "{EEF89893-A6A9-4C02-818C-D116C8EAE0EF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ElasticSearchProcessor", "Yi.Framework.ElasticSearchProcessor\Yi.Framework.ElasticSearchProcessor.csproj", "{EEF89893-A6A9-4C02-818C-D116C8EAE0EF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.MSUnitTest", "Yi.Framework.MSUnitTest\Yi.Framework.MSUnitTest.csproj", "{531255B3-9669-4BC1-B4E5-A0C6E0540F0D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.MSUnitTest", "Yi.Framework.MSUnitTest\Yi.Framework.MSUnitTest.csproj", "{531255B3-9669-4BC1-B4E5-A0C6E0540F0D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.PageDetail", "Yi.Framework.PageDetail\Yi.Framework.PageDetail.csproj", "{637501E2-A32E-485C-8680-ED863D1793C2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.PageDetail", "Yi.Framework.PageDetail\Yi.Framework.PageDetail.csproj", "{637501E2-A32E-485C-8680-ED863D1793C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Job", "Yi.Framework.Task\Yi.Framework.Job.csproj", "{F1C990DD-32C3-4F02-83B0-6E52B18B0B17}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -103,6 +105,10 @@ Global
{637501E2-A32E-485C-8680-ED863D1793C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{637501E2-A32E-485C-8680-ED863D1793C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{637501E2-A32E-485C-8680-ED863D1793C2}.Release|Any CPU.Build.0 = Release|Any CPU
{F1C990DD-32C3-4F02-83B0-6E52B18B0B17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1C990DD-32C3-4F02-83B0-6E52B18B0B17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1C990DD-32C3-4F02-83B0-6E52B18B0B17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1C990DD-32C3-4F02-83B0-6E52B18B0B17}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -122,6 +128,7 @@ Global
{EEF89893-A6A9-4C02-818C-D116C8EAE0EF} = {D6B44435-EAFA-4D55-90D0-3AF80485FB83}
{531255B3-9669-4BC1-B4E5-A0C6E0540F0D} = {C90E38FB-69EA-4997-8B3A-2C71EFA65B2B}
{637501E2-A32E-485C-8680-ED863D1793C2} = {026D2797-07D1-4BA5-8070-50CDE0258C59}
{F1C990DD-32C3-4F02-83B0-6E52B18B0B17} = {9ABAF6B1-6C02-498A-90A2-ABC1140CF89A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1ED77A6E-377F-4EEF-A3D0-D65C94657DAF}