Compare commits

..

51 Commits

Author SHA1 Message Date
chenchun
6b47ae232d feat:完成hangfire接入 2024-11-15 18:17:53 +08:00
chenchun
536c3cc56b feat: 支持store 缓存和redis切换 2024-11-15 17:01:39 +08:00
chenchun
b75a8cb60d feat: 全量quarzt到hangfire任务 2024-11-15 16:45:01 +08:00
橙子
17bc4ade84 fix: 修复审计日志错误信息 2024-11-10 17:33:20 +08:00
橙子
aea0896356 fix: 修复GetUserAsync报错问题 2024-11-10 17:23:00 +08:00
chenchun
ae82a2d1cf style: 修改描述 2024-11-08 13:56:43 +08:00
chenchun
2412bc1da4 style: 修改开始描述 2024-11-08 13:41:03 +08:00
chenchun
42b00515eb Merge branch 'refs/heads/tool-dev' into abp 2024-11-08 12:36:26 +08:00
chenchun
f3c5d0862b feat: 完成tool 2024-11-08 12:35:54 +08:00
chenchun
e832921edf chorm: 构建 2024-11-08 11:21:10 +08:00
chenchun
0c0ead26c0 style: 删除多余 2024-11-08 11:11:27 +08:00
chenchun
f9a018638b feat: 去除sample 2024-11-08 11:10:45 +08:00
chenchun
d5ca8ddf1e feat: 完成模板从gitee上获取 2024-11-07 17:35:22 +08:00
橙子
650c29e75a !77 修正Ruoyi查询时间条件为时间的错误问题
Merge pull request !77 from Po/N/A
2024-11-06 15:51:24 +00:00
橙子
ed5c20c612 feat: 支持版本号 2024-11-06 00:05:29 +08:00
橙子
49f1d1a8fa test: 补充测试 2024-11-05 22:36:22 +08:00
橙子
a87d6345c2 feat: 完成2.0重构 2024-11-05 22:22:42 +08:00
橙子
d83db53acb feat: 完成tool搭建 2024-11-05 22:12:30 +08:00
chenchun
c944bd3b0e feat: 搭建tool 2024-11-05 18:50:15 +08:00
chenchun
751cc3cadb feat: 支持不同类型的用户id、主键 2024-11-05 16:45:30 +08:00
Po
80fe1116a8 修正Ruoyi查询时间条件为时间的错误问题
Signed-off-by: Po <448443959@qq.com>
2024-11-05 00:26:59 +00:00
橙子
9aaa88ef51 refactor: 重构tool工具 2024-11-03 23:15:55 +08:00
橙子
ef2d00a254 feat: 新增bbs商城领域 2024-11-02 21:06:14 +08:00
橙子
d38159f68b chorm: 构建 2024-11-02 19:52:41 +08:00
橙子
dd29c9a2fa feat: bbs新增商城页面初版 2024-11-02 19:50:01 +08:00
橙子
ca1b8a728d feat: bbs支持滚动主题 2024-11-02 17:34:48 +08:00
橙子
6b647cf4ea feat: 合并pure pr 2024-11-02 16:17:48 +08:00
橙子
0e6f79c28e feat: 调整抽奖概率,提高 2024-11-02 15:48:28 +08:00
橙子
894d4eb051 fix: 修复时间 2024-11-02 15:34:53 +08:00
橙子
8d9c5bb762 feat: bbs完善钱钱实时变化 2024-11-02 15:28:45 +08:00
志福
7a916fc78e 添加Pure Config页面 2024-11-01 21:59:22 +08:00
志福
73db2a202a 增加Pure Config页面 2024-11-01 21:58:08 +08:00
橙子
f9890bdc7f feat: 提高审计日志记录 2024-10-31 21:21:31 +08:00
chenchun
8a0c0de8a1 style: 增加评论长度 2024-10-30 11:49:02 +08:00
橙子
8c940126b5 feat: 新增yarn 2024-10-29 22:08:31 +08:00
橙子
71b7b7cc79 feat:api格式从newtonjson改为微软 2024-10-27 21:48:39 +08:00
橙子
f6be4ad7ac feat: bbs支持富文本 2024-10-26 20:26:54 +08:00
橙子
f6cbe899c6 fix: 修复NewtonsoftJson问题 2024-10-26 15:40:45 +08:00
橙子
7598c8319f feat: 去除多余引用 2024-10-26 15:17:19 +08:00
橙子
a798f36529 feat: 补充租户引用 2024-10-26 15:15:09 +08:00
chenchun
59d9674aeb Merge branch 'refs/heads/pr_74' into abp
# Conflicts:
#	Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/DictionaryService.cs
2024-10-25 17:31:01 +08:00
橙子
36ed5400be !73 字典详情前端页面解决排序不显示
Merge pull request !73 from 呆呆0518/Staging
2024-10-25 06:47:56 +00:00
hao
6378c69764 字典详情crud实体增加OrderNum,列表增加倒序 2024-10-25 14:46:26 +08:00
呆呆0518
b44db20938 前端页面解决排序不显示 2024-10-25 14:36:05 +08:00
橙子
61cd7b42d4 !72 岗位排序无效问题修复
Merge pull request !72 from 窗外的麻雀/abp
2024-10-25 02:03:22 +00:00
hao
77d64796e0 岗位排序无效 2024-10-25 09:36:56 +08:00
hao
a4001c21b1 岗位修改排序失败 2024-10-25 09:36:04 +08:00
橙子
9e1d01774f !71 Ruoyi底部分页栏太靠右了,显示不全
Merge pull request !71 from Po/N/A
2024-10-22 06:51:13 +00:00
Po
be4f0a2a90 Ruoyi底部分页栏太靠左了,显示不全
Signed-off-by: Po <448443959@qq.com>
2024-10-22 02:23:00 +00:00
橙子
c45c17748e feat: 支持代理转发ip功能后去 2024-10-21 23:28:52 +08:00
橙子
57ad7ae1a3 feat: 完善请求日志过滤 2024-10-21 23:07:44 +08:00
150 changed files with 2484 additions and 11652 deletions

1
.gitignore vendored
View File

@@ -269,6 +269,7 @@ dist
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Production.json
/Yi.Abp.Net8/test/Yi.Abp.Test/appsettings.Development.json
/Yi.Abp.Net8/test/Yi.Abp.Test/appsettings.Production.json
/Yi.Abp.Net8/tool/Yi.Abp.Tool.Web/appsettings.Development.json
database_backup
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Staging.json
/Yi.Abp.Net8/src/Yi.Abp.Web/logs/

View File

@@ -80,20 +80,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuditLogging.S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AspNetCore.Authentication.OAuth", "framework\Yi.Framework.AspNetCore.Authentication.OAuth\Yi.Framework.AspNetCore.Authentication.OAuth.csproj", "{791AC2FA-50D3-4408-8D68-31DA72F608BE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{01300F0F-686E-47B3-821D-12424177867B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Web", "sample\Acme.BookStore.Web\Acme.BookStore.Web.csproj", "{576DBC97-4E5D-4444-B65C-F41649A5F8E0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Shared", "sample\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj", "{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain", "sample\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj", "{B615847F-8568-41D1-8B7E-63D61AE69F3D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application.Contracts", "sample\Acme.BookStore.Application.Contracts\Acme.BookStore.Application.Contracts.csproj", "{20827DB5-5CDE-491A-82E8-3CAB82618C1E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application", "sample\Acme.BookStore.Application\Acme.BookStore.Application.csproj", "{320273B6-7AE3-42DA-9675-D9AD4928A289}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.SqlSugarCore", "sample\Acme.BookStore.SqlSugarCore\Acme.BookStore.SqlSugarCore.csproj", "{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Test", "test\Yi.Abp.Test\Yi.Abp.Test.csproj", "{68627BC2-F049-4C69-AD17-81DF9478E8CE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenant-management", "tenant-management", "{499A8C71-7892-42D0-A77E-48756E1EFF16}"
@@ -170,6 +156,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.HttpApi.Client"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.SettingManagement.Application", "module\setting-management\Yi.Framework.SettingManagement.Application\Yi.Framework.SettingManagement.Application.csproj", "{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.BackgroundWorkers.Hangfire", "framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj", "{862CA181-BEE6-4870-82D2-B662E527ED8C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -276,30 +264,6 @@ Global
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{791AC2FA-50D3-4408-8D68-31DA72F608BE}.Release|Any CPU.Build.0 = Release|Any CPU
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{576DBC97-4E5D-4444-B65C-F41649A5F8E0}.Release|Any CPU.Build.0 = Release|Any CPU
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D}.Release|Any CPU.Build.0 = Release|Any CPU
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B615847F-8568-41D1-8B7E-63D61AE69F3D}.Release|Any CPU.Build.0 = Release|Any CPU
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20827DB5-5CDE-491A-82E8-3CAB82618C1E}.Release|Any CPU.Build.0 = Release|Any CPU
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Debug|Any CPU.Build.0 = Debug|Any CPU
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Release|Any CPU.ActiveCfg = Release|Any CPU
{320273B6-7AE3-42DA-9675-D9AD4928A289}.Release|Any CPU.Build.0 = Release|Any CPU
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7}.Release|Any CPU.Build.0 = Release|Any CPU
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68627BC2-F049-4C69-AD17-81DF9478E8CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -428,6 +392,10 @@ Global
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.Build.0 = Release|Any CPU
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -461,12 +429,6 @@ Global
{73CCF2C4-B9FD-44AB-8D4B-0A421805B094} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
{791AC2FA-50D3-4408-8D68-31DA72F608BE} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
{576DBC97-4E5D-4444-B65C-F41649A5F8E0} = {01300F0F-686E-47B3-821D-12424177867B}
{D7F8BD42-F6A2-4F0A-9212-391B5185A99D} = {01300F0F-686E-47B3-821D-12424177867B}
{B615847F-8568-41D1-8B7E-63D61AE69F3D} = {01300F0F-686E-47B3-821D-12424177867B}
{20827DB5-5CDE-491A-82E8-3CAB82618C1E} = {01300F0F-686E-47B3-821D-12424177867B}
{320273B6-7AE3-42DA-9675-D9AD4928A289} = {01300F0F-686E-47B3-821D-12424177867B}
{70CCBD89-C0A1-4AC8-9AFA-C86C356DFDD7} = {01300F0F-686E-47B3-821D-12424177867B}
{68627BC2-F049-4C69-AD17-81DF9478E8CE} = {0D10EEF2-FBAE-4C72-B816-A52823FC299B}
{499A8C71-7892-42D0-A77E-48756E1EFF16} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
{FA5BBAA1-08DC-472F-BB2C-5314E59D1556} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
@@ -503,6 +465,7 @@ Global
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
{C8F97775-D903-4365-A4FF-3DA97E318CD2} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
{862CA181-BEE6-4870-82D2-B662E527ED8C} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}

View File

@@ -0,0 +1,37 @@
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Volo.Abp.AspNetCore.WebClientInfo;
namespace Yi.Framework.AspNetCore;
public class RealIpHttpContextWebClientInfoProvider : HttpContextWebClientInfoProvider
{
public RealIpHttpContextWebClientInfoProvider(ILogger<HttpContextWebClientInfoProvider> logger,
IHttpContextAccessor httpContextAccessor) : base(logger, httpContextAccessor)
{
}
protected override string? GetClientIpAddress()
{
try
{
var httpContext = HttpContextAccessor.HttpContext;
var headers = httpContext?.Request?.Headers;
if (headers != null && headers.ContainsKey("X-Forwarded-For"))
{
httpContext.Connection.RemoteIpAddress =
IPAddress.Parse(headers["X-Forwarded-For"].FirstOrDefault());
}
return httpContext?.Connection?.RemoteIpAddress?.ToString();
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
return null;
}
}
}

View File

@@ -11,6 +11,7 @@ using Newtonsoft.Json.Linq;
using Swashbuckle.AspNetCore.SwaggerGen;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.WebClientInfo;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
using Yi.Framework.AspNetCore.Mvc;
@@ -22,6 +23,11 @@ namespace Yi.Framework.AspNetCore
)]
public class YiFrameworkAspNetCoreModule : AbpModule
{
public override void PostConfigureServices(ServiceConfigurationContext context)
{
var services = context.Services;
services.Replace(new ServiceDescriptor(typeof(IWebClientInfoProvider),
typeof(RealIpHttpContextWebClientInfoProvider), ServiceLifetime.Transient));
}
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.BackgroundWorkers.Hangfire" Version="$(AbpVersion)" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,27 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.BackgroundWorkers.Hangfire;
namespace Yi.Framework.BackgroundWorkers.Hangfire;
[DependsOn(typeof(AbpBackgroundWorkersHangfireModule))]
public class YiFrameworkBackgroundWorkersHangfireModule:AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddConventionalRegistrar(new YiHangfireConventionalRegistrar());
}
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
//定时任务自动注入Abp默认只有在Quartz才实现
var backgroundWorkerManager = context.ServiceProvider.GetRequiredService<IBackgroundWorkerManager>();
var works = context.ServiceProvider.GetServices<IHangfireBackgroundWorker>();
foreach (var work in works)
{
await backgroundWorkerManager.AddAsync(work);
}
}
}

View File

@@ -0,0 +1,20 @@
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.DependencyInjection;
namespace Yi.Framework.BackgroundWorkers.Hangfire;
public class YiHangfireConventionalRegistrar : DefaultConventionalRegistrar
{
protected override bool IsConventionalRegistrationDisabled(Type type)
{
return !typeof(IHangfireBackgroundWorker).IsAssignableFrom(type) || base.IsConventionalRegistrationDisabled(type);
}
protected override List<Type> GetExposedServiceTypes(Type type)
{
return new List<Type>()
{
typeof(IHangfireBackgroundWorker)
};
}
}

View File

@@ -0,0 +1,27 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Yi.Framework.Core.Json;
public class DatetimeJsonConverter : JsonConverter<DateTime>
{
private string _format;
public DatetimeJsonConverter(string format="yyyy-MM-dd HH:mm:ss")
{
_format = format;
}
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if(reader.TokenType==JsonTokenType.String)
{
if (DateTime.TryParse(reader.GetString(), out DateTime dateTime)) return dateTime;
}
return reader.GetDateTime();
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_format));
}
}

View File

@@ -36,15 +36,18 @@ namespace Yi.Framework.SqlSugarCore
protected virtual bool IsSoftDeleteFilterEnabled => DataFilter?.IsEnabled<ISoftDelete>() ?? false;
private IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
private IEntityChangeEventHelper EntityChangeEventHelper =>
LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
private ISerializeService SerializeService=> LazyServiceProvider.LazyGetRequiredService<ISerializeService>();
private ISerializeService SerializeService => LazyServiceProvider.LazyGetRequiredService<ISerializeService>();
public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient)
{
SqlSugarClient = sqlSugarClient;
}
public SqlSugarDbContext(IAbpLazyServiceProvider lazyServiceProvider)
{
LazyServiceProvider = lazyServiceProvider;
@@ -73,12 +76,14 @@ namespace Yi.Framework.SqlSugarCore
protected virtual string GetCurrentConnectionString()
{
var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService<IConnectionStringResolver>();
var connectionString = connectionStringResolver.ResolveAsync().ConfigureAwait(false).GetAwaiter().GetResult();
var connectionString =
connectionStringResolver.ResolveAsync().ConfigureAwait(false).GetAwaiter().GetResult();
if (string.IsNullOrWhiteSpace(connectionString))
{
Check.NotNull(Options.Url, "dbUrl未配置");
}
return connectionString!;
}
@@ -92,6 +97,7 @@ namespace Yi.Framework.SqlSugarCore
return dbTypeFromTenantName.Value;
}
}
Check.NotNull(Options.DbType, "默认DbType未配置");
return Options.DbType!.Value;
}
@@ -126,7 +132,6 @@ namespace Yi.Framework.SqlSugarCore
}
/// <summary>
/// 上下文对象扩展
/// </summary>
@@ -138,21 +143,23 @@ namespace Yi.Framework.SqlSugarCore
{
sqlSugarClient.QueryFilter.AddTableFilter<ISoftDelete>(u => u.IsDeleted == false);
}
if (IsMultiTenantFilterEnabled)
{
//表达式里只能有具体值,不能运算
var expressionCurrentTenant = CurrentTenant.Id ?? null;
sqlSugarClient.QueryFilter.AddTableFilter<IMultiTenant>(u => u.TenantId == expressionCurrentTenant);
}
CustomDataFilter(sqlSugarClient);
}
protected virtual void CustomDataFilter(ISqlSugarClient sqlSugarClient)
{
}
protected virtual void DataExecuted(object oldValue, DataAfterModel entityInfo)
{
}
/// <summary>
@@ -174,25 +181,34 @@ namespace Yi.Framework.SqlSugarCore
entityInfo.SetValue(DateTime.Now);
}
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
else if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
{
if (CurrentUser.Id != null)
if (typeof(Guid?) == entityInfo.EntityColumnInfo.PropertyInfo.PropertyType)
{
entityInfo.SetValue(CurrentUser.Id);
}
}
break;
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName.Equals(nameof(IEntity<Guid>.Id)))
{
//主键为空或者为默认最小值
if (Guid.Empty.Equals(oldValue))
{
entityInfo.SetValue(GuidGenerator.Create());
if (CurrentUser.Id != null)
{
entityInfo.SetValue(CurrentUser.Id);
}
}
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
break;
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName.Equals(nameof(IEntity<Guid>.Id)))
{
//类型为guid
if (typeof(Guid) == entityInfo.EntityColumnInfo.PropertyInfo.PropertyType)
{
//主键为空或者为默认最小值
if (Guid.Empty.Equals(oldValue))
{
entityInfo.SetValue(GuidGenerator.Create());
}
}
}
else if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
{
//为空或者为默认最小值
if (DateTime.MinValue.Equals(oldValue))
@@ -200,21 +216,26 @@ namespace Yi.Framework.SqlSugarCore
entityInfo.SetValue(DateTime.Now);
}
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
else if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
{
if (CurrentUser.Id is not null)
//类型为guid
if (typeof(Guid?) == entityInfo.EntityColumnInfo.PropertyInfo.PropertyType)
{
entityInfo.SetValue(CurrentUser.Id);
if (CurrentUser.Id is not null)
{
entityInfo.SetValue(CurrentUser.Id);
}
}
}
if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
else if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
{
if (CurrentTenant.Id is not null)
{
entityInfo.SetValue(CurrentTenant.Id);
}
}
break;
}
@@ -227,6 +248,7 @@ namespace Yi.Framework.SqlSugarCore
{
EntityChangeEventHelper.PublishEntityCreatedEvent(entityInfo.EntityValue);
}
break;
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
@@ -243,8 +265,8 @@ namespace Yi.Framework.SqlSugarCore
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityInfo.EntityValue);
}
}
break;
case DataFilterType.DeleteByObject:
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
@@ -254,14 +276,13 @@ namespace Yi.Framework.SqlSugarCore
{
foreach (var entityValue in entityValues)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entityValue);
}
}
}
break;
}
}
/// <summary>
@@ -280,7 +301,6 @@ namespace Yi.Framework.SqlSugarCore
sb.AppendLine("===============================");
Logger.CreateLogger<SqlSugarDbContext>().LogDebug(sb.ToString());
}
}
/// <summary>
@@ -306,14 +326,14 @@ namespace Yi.Framework.SqlSugarCore
{
if (property.Name == nameof(IHasConcurrencyStamp.ConcurrencyStamp)) //带版本号并发更新
{
// column.IsOnlyIgnoreInsert = true;
// column.IsOnlyIgnoreUpdate = true;
column.IsEnableUpdateVersionValidation = true;
}
if (property.PropertyType == typeof(ExtraPropertyDictionary))
{
column.IsIgnore = true;
}
if (property.Name == nameof(Entity<object>.Id))
{
column.IsPrimarykey = true;
@@ -328,11 +348,13 @@ namespace Yi.Framework.SqlSugarCore
{
Directory.CreateDirectory(directoryName);
}
switch (Options.DbType)
{
case DbType.MySql:
//MySql
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.sql");//mysql 只支持.net core
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database,
$"{Path.Combine(directoryName, fileName)}.sql"); //mysql 只支持.net core
break;
@@ -344,19 +366,14 @@ namespace Yi.Framework.SqlSugarCore
case DbType.SqlServer:
//SqlServer
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.bak"/*服务器路径*/);//第一个参数库名
SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database,
$"{Path.Combine(directoryName, fileName)}.bak" /*服务器路径*/); //第一个参数库名
break;
default:
throw new NotImplementedException("其他数据库备份未实现");
}
}
}
}
}

View File

@@ -16,6 +16,7 @@ public class AuditingStore : IAuditingStore, ITransientDependency
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected AbpAuditingOptions Options { get; }
protected IAuditLogInfoToAuditLogConverter Converter { get; }
public AuditingStore(
IAuditLogRepository auditLogRepository,
IUnitOfWorkManager unitOfWorkManager,
@@ -52,10 +53,10 @@ public class AuditingStore : IAuditingStore, ITransientDependency
protected virtual async Task SaveLogAsync(AuditLogInfo auditInfo)
{
Logger.LogDebug("Yi-请求追踪:" + JsonHelper.ObjToStr(auditInfo, "yyyy-MM-dd HH:mm:ss"));
using (var uow = UnitOfWorkManager.Begin(true))
{
await AuditLogRepository.InsertAsync(await Converter.ConvertAsync(auditInfo));
await uow.CompleteAsync();
}
// using (var uow = UnitOfWorkManager.Begin(true,isTransactional:false))
// {
await AuditLogRepository.InsertAsync(await Converter.ConvertAsync(auditInfo));
// await uow.CompleteAsync();
// }
}
}
}

View File

@@ -22,6 +22,7 @@ public class AuditLogActionEntity : Entity<Guid>, IMultiTenant
public virtual string? MethodName { get; protected set; }
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
public virtual string? Parameters { get; protected set; }
public virtual DateTime? ExecutionTime { get; protected set; }

View File

@@ -103,6 +103,7 @@ namespace Yi.Framework.AuditLogging.Domain.Entities
public virtual string? CorrelationId { get; set; }
[SugarColumn(Length = 2000)]
public virtual string? BrowserInfo { get; protected set; }
public virtual string? HttpMethod { get; protected set; }

View File

@@ -1,8 +1,8 @@
using FreeRedis;
using Hangfire;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Quartz;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
@@ -15,23 +15,27 @@ using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Bbs.Application.Jobs;
public class AccessLogCacheJob : QuartzBackgroundWorkerBase
public class AccessLogCacheJob : HangfireBackgroundWorkerBase
{
private readonly ILocalEventBus _localEventBus;
public AccessLogCacheJob(ILocalEventBus localEventBus)
{
_localEventBus = localEventBus;
JobDetail = JobBuilder.Create<AccessLogCacheJob>().WithIdentity(nameof(AccessLogCacheJob))
.Build();
RecurringJobId = "访问日志写入缓存";
//每10秒执行一次将本地缓存转入redis防止丢数据
CronExpression = "*/10 * * * * *";
//
// JobDetail = JobBuilder.Create<AccessLogCacheJob>().WithIdentity(nameof(AccessLogCacheJob))
// .Build();
//每10秒执行一次将本地缓存转入redis防止丢数据
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
.WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever();; })
.Build();
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
// .WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever();; })
// .Build();
}
public override async Task Execute(IJobExecutionContext context)
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
await _localEventBus.PublishAsync(new AccessLogResetArgs());
}

View File

@@ -1,11 +1,9 @@
using FreeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Quartz;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Yi.Framework.Bbs.Domain.Entities;
using Yi.Framework.Bbs.Domain.Shared.Caches;
using Yi.Framework.Bbs.Domain.Shared.Enums;
@@ -13,7 +11,7 @@ using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Bbs.Application.Jobs;
public class AccessLogStoreJob : QuartzBackgroundWorkerBase
public class AccessLogStoreJob : HangfireBackgroundWorkerBase
{
private readonly ISqlSugarRepository<AccessLogAggregateRoot> _repository;
@@ -45,18 +43,23 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
public AccessLogStoreJob(ISqlSugarRepository<AccessLogAggregateRoot> repository)
{
_repository = repository;
JobDetail = JobBuilder.Create<AccessLogStoreJob>().WithIdentity(nameof(AccessLogStoreJob))
.Build();
RecurringJobId = "访问日志写入数据库";
//每分钟执行一次
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
.WithCronSchedule("0 * * * * ?")
.Build();
CronExpression = "0 * * * * ?";
// JobDetail = JobBuilder.Create<AccessLogStoreJob>().WithIdentity(nameof(AccessLogStoreJob))
// .Build();
// //每分钟执行一次
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogStoreJob))
// .WithCronSchedule("0 * * * * ?")
// .Build();
}
public override async Task Execute(IJobExecutionContext context)
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
if (EnableRedisCache)
{

View File

@@ -1,5 +1,4 @@
using Quartz;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Domain.Managers;
namespace Yi.Framework.Bbs.Application.Jobs;
@@ -7,20 +6,25 @@ namespace Yi.Framework.Bbs.Application.Jobs;
/// <summary>
/// 每日任务job
/// </summary>
public class AssignmentExpireTimeOutJob : QuartzBackgroundWorkerBase
public class AssignmentExpireTimeOutJob : HangfireBackgroundWorkerBase
{
private readonly AssignmentManager _assignmentManager;
public AssignmentExpireTimeOutJob(AssignmentManager assignmentManager)
{
_assignmentManager = assignmentManager;
JobDetail = JobBuilder.Create<AssignmentExpireTimeOutJob>().WithIdentity(nameof(AssignmentExpireTimeOutJob)).Build();
//每个小时整点执行一次
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).WithCronSchedule("0 0 * * * ?")
.Build();
RecurringJobId = "每日任务系统超时检测";
//每分钟执行一次
CronExpression = "0 * * * * ?";
//
// JobDetail = JobBuilder.Create<AssignmentExpireTimeOutJob>().WithIdentity(nameof(AssignmentExpireTimeOutJob)).Build();
// //每个小时整点执行一次
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(AssignmentExpireTimeOutJob)).WithCronSchedule("0 0 * * * ?")
// .Build();
}
public override async Task Execute(IJobExecutionContext context)
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
await _assignmentManager.ExpireTimeoutAsync();
}

View File

@@ -1,20 +1,24 @@
using Quartz;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Domain.Managers;
namespace Yi.Framework.Bbs.Application.Jobs
{
public class InterestRecordsJob : QuartzBackgroundWorkerBase
public class InterestRecordsJob : HangfireBackgroundWorkerBase
{
private BankManager _bankManager;
public InterestRecordsJob(BankManager bankManager)
{
_bankManager = bankManager;
JobDetail = JobBuilder.Create<InterestRecordsJob>().WithIdentity(nameof(InterestRecordsJob)).Build();
RecurringJobId = "银行利息积分刷新";
//每个小时整点执行一次
Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).WithCronSchedule("0 0 * * * ?").Build();
CronExpression = "0 0 * * * ?";
// JobDetail = JobBuilder.Create<InterestRecordsJob>().WithIdentity(nameof(InterestRecordsJob)).Build();
//
// //每个小时整点执行一次
//
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob)).WithCronSchedule("0 0 * * * ?").Build();
//测试
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(InterestRecordsJob))
@@ -23,7 +27,8 @@ namespace Yi.Framework.Bbs.Application.Jobs
// .RepeatForever())
//.Build();
}
public override async Task Execute(IJobExecutionContext context)
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
//创建一个记录,莫得了
await _bankManager.GetCurrentInterestRate();

View File

@@ -27,13 +27,19 @@ namespace Yi.Framework.Bbs.Application.Services
var userEntity = await _bbsUserManager._userRepository.GetFirstAsync(x => x.UserName == userNameOrUserId);
if (userEntity == null)
{
throw new Volo.Abp.UserFriendlyException("该用户不存在");
throw new UserFriendlyException("该用户不存在");
}
userId= userEntity.Id;
}
var output =await _bbsUserManager.GetBbsUserInfoAsync(userId);
//不是自己
if (CurrentUser.Id != output.Id)
{
output.Phone = null;
output.Email=null;
}
return output!;
}
}

View File

@@ -136,6 +136,11 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
[Authorize]
public override async Task<CommentGetOutputDto> CreateAsync(CommentCreateInputVo input)
{
if (input.Content.Length<=6)
{
throw new UserFriendlyException("评论长度至少大于6");
}
var discuess = await _discussRepository.GetFirstAsync(x => x.Id == input.DiscussId);
if (discuess is null)
{

View File

@@ -16,7 +16,7 @@ namespace Yi.Framework.Bbs.Application.Services.Integral
/// <summary>
/// 大转盘
/// Todo: 可放入领域层
/// Todo: 可放入领域层,但是太简单了,不重要
/// </summary>
/// <returns></returns>
[Authorize]
@@ -32,13 +32,7 @@ namespace Yi.Framework.Bbs.Application.Services.Integral
int[] values = new int[10] { 0, 10, 30, 50, 60, 80, 90, 100, 200, 666 };
var index = GetWheelIndex();
var value = values[index] - 50;
////不存在负数钱钱
//if (value < 0)
//{
// value = 0;
//}
//修改钱钱,如果钱钱不足,直接会丢出去,那本次抽奖将无效
await _localEventBus.PublishAsync(new MoneyChangeEventArgs { UserId = CurrentUser.Id!.Value, Number = value }, false);
@@ -47,7 +41,7 @@ namespace Yi.Framework.Bbs.Application.Services.Integral
private int GetWheelIndex()
{
int[] probabilities = { 30, 40, 30, 15, 15, 10, 4, 3, 2, 1 };
int[] probabilities = {5 , 30, 40, 30, 20, 10, 4, 3, 2, 1 };
int total = 0;
foreach (var prob in probabilities)

View File

@@ -0,0 +1,9 @@
namespace Yi.Framework.Bbs.Domain.Shared.Enums;
public enum GoodsTypeEnum
{
/// <summary>
/// 申请类型
/// </summary>
Apply
}

View File

@@ -19,5 +19,10 @@ namespace Yi.Framework.Bbs.Domain.Shared.Enums
/// 广播
/// </summary>
Broadcast,
/// <summary>
/// 钱钱
/// </summary>
Money
}
}

View File

@@ -16,6 +16,13 @@ namespace Yi.Framework.Bbs.Domain.Shared.Etos
Message = message;
}
public BbsNoticeEventArgs( NoticeTypeEnum noticeType, Guid acceptUserId, string message)
{
NoticeType = noticeType;
AcceptUserId = acceptUserId;
Message = message;
}
/// <summary>
/// 发送广播
/// </summary>

View File

@@ -31,7 +31,7 @@ namespace Yi.Framework.Bbs.Domain.Entities.Forum
public override Guid Id { get; protected set; }
public bool IsDeleted { get; set; }
[SugarColumn(Length = 500)]
[SugarColumn(Length = 2000)]
public string Content { get; set; }
public Guid DiscussId { get; set; }

View File

@@ -0,0 +1,73 @@
using SqlSugar;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Yi.Framework.Bbs.Domain.Shared.Enums;
namespace Yi.Framework.Bbs.Domain.Entities.Shop;
/// <summary>
/// 商品定义表
/// </summary>
[SugarTable("BbsGoods")]
public class BbsGoodsAggregateRoot: AggregateRoot<Guid>, IHasCreationTime
{
/// <summary>
/// 上架时间
/// </summary>
public DateTime CreationTime { get; set; }
/// <summary>
/// 商品类型
/// </summary>
public GoodsTypeEnum GoodsType{ get; set; }
/// <summary>
/// 下架时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 商品名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 每人限购数量
/// </summary>
public int LimitNumber { get; set; }
/// <summary>
/// 当前库存数量
/// </summary>
public int StockNumber { get; set; }
/// <summary>
/// 商品图片url
/// </summary>
public string ImageUrl { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Describe { get; set; }
/// <summary>
/// 编号
/// </summary>
public string Code { get; set; }
/// <summary>
/// 所需钱钱
/// </summary>
public decimal NeedMoney { get; set; }
/// <summary>
/// 所需价值
/// </summary>
public decimal NeedValue { get; set; }
/// <summary>
/// 所需积分
/// </summary>
public decimal NeedPoints { get; set; }
}

View File

@@ -0,0 +1,32 @@
using SqlSugar;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
namespace Yi.Framework.Bbs.Domain.Entities.Shop;
/// <summary>
/// 商品申请记录表
/// </summary>
[SugarTable("BbsGoodsApply")]
public class BbsGoodsApplyAggregateRoot: AggregateRoot<Guid>, IHasCreationTime
{
/// <summary>
/// 商品id
/// </summary>
public Guid GoodsId { get; set; }
/// <summary>
/// 申请时间
/// </summary>
public DateTime CreationTime { get; set; }
/// <summary>
/// 申请人用户id
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 联系方式
/// </summary>
public string ContactInformation { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Yi.Framework.Bbs.Domain.Entities.Shop.ValueObjects;
public class ShippingAddress
{
}

View File

@@ -25,23 +25,40 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
}
public async Task HandleEventAsync(BbsNoticeEventArgs eventData)
{
//离线存储
var entity= await _repository.InsertReturnEntityAsync(new BbsNoticeAggregateRoot(eventData.NoticeType, eventData.Message, eventData.AcceptUserId));
switch (eventData.NoticeType)
//是否需要离线存储
bool isStore = true;
var now = DateTime.Now;
switch (eventData.NoticeType)
{
case Shared.Enums.NoticeTypeEnum.Personal:
if (BbsNoticeHub.HubUserModels.TryGetValue(eventData.AcceptUserId.ToString(), out var hubUserModel))
{
_hubContext.Clients.Client(hubUserModel.ConnnectionId).SendAsync(NoticeTypeEnum.Personal.ToString(), eventData.Message,entity.CreationTime);
_hubContext.Clients.Client(hubUserModel.ConnnectionId).SendAsync(NoticeTypeEnum.Personal.ToString(), eventData.Message,now);
}
break;
case Shared.Enums.NoticeTypeEnum.Broadcast:
_hubContext.Clients.All.SendAsync(NoticeTypeEnum.Broadcast.ToString(), eventData.Message);
break;
case Shared.Enums.NoticeTypeEnum.Money:
if (BbsNoticeHub.HubUserModels.TryGetValue(eventData.AcceptUserId.ToString(), out var hubUserModel2))
{
_hubContext.Clients.Client(hubUserModel2.ConnnectionId).SendAsync(NoticeTypeEnum.Money.ToString(), eventData.Message,now);
}
isStore = false;
break;
default:
break;
}
if (isStore)
{ //离线存储
var entity= await _repository.InsertReturnEntityAsync(new BbsNoticeAggregateRoot(eventData.NoticeType, eventData.Message, eventData.AcceptUserId){CreationTime = now});
}
}
}
}

View File

@@ -1,8 +1,10 @@
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Yi.Framework.Bbs.Domain.Entities;
using Yi.Framework.Bbs.Domain.Shared.Consts;
using Yi.Framework.Bbs.Domain.Shared.Enums;
using Yi.Framework.Bbs.Domain.Shared.Etos;
using Yi.Framework.SqlSugarCore.Abstractions;
@@ -11,9 +13,11 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
public class MoneyChangeEventHandler : ILocalEventHandler<MoneyChangeEventArgs>, ITransientDependency
{
private ISqlSugarRepository<BbsUserExtraInfoEntity> _userInfoRepository;
public MoneyChangeEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userInfoRepository)
private ILocalEventBus _localEventBus;
public MoneyChangeEventHandler(ISqlSugarRepository<BbsUserExtraInfoEntity> userInfoRepository, ILocalEventBus localEventBus)
{
_userInfoRepository = userInfoRepository;
_localEventBus = localEventBus;
}
public async Task HandleEventAsync(MoneyChangeEventArgs eventData)
{
@@ -28,6 +32,9 @@ namespace Yi.Framework.Bbs.Domain.EventHandlers
await _userInfoRepository._Db.Updateable<BbsUserExtraInfoEntity>()
.SetColumns(it => it.Money == it.Money + eventData.Number)
.Where(x => x.UserId == eventData.UserId).ExecuteCommandAsync();
await _localEventBus.PublishAsync(new BbsNoticeEventArgs(NoticeTypeEnum.Money, eventData.UserId,eventData.Number.ToString()), false);
}
}
}

View File

@@ -0,0 +1,11 @@
using Volo.Abp.Domain.Services;
namespace Yi.Framework.Bbs.Domain.Managers;
/// <summary>
/// bbs商品领域
/// </summary>
public class BbsShopManager: DomainService
{
}

View File

@@ -78,7 +78,12 @@ namespace Yi.Framework.ChatHub.Domain.Managers
public async Task<ChatOnlineUserCacheItem?> GetUserAsync(Guid userId)
{
var key = new ChatOnlineUserCacheKey(CacheKeyPrefix);
var cacheUser = System.Text.Json.JsonSerializer.Deserialize<ChatOnlineUserCacheItem>(await RedisClient.HGetAsync(key.GetKey(), key.GetField(userId)));
var cacheUserOrNull= await RedisClient.HGetAsync(key.GetKey(), key.GetField(userId));
if (cacheUserOrNull is null)
{
return null;
}
var cacheUser = System.Text.Json.JsonSerializer.Deserialize<ChatOnlineUserCacheItem>(cacheUserOrNull);
return cacheUser;
}
}

View File

@@ -4,8 +4,8 @@
{
public string Phone { get; set; }
public string? Uuid { get; set; }
public string Uuid { get; set; }
public string? Code { get; set; }
public string Code { get; set; }
}
}

View File

@@ -5,6 +5,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary
/// </summary>
public class DictionaryCreateInputVo
{
public int OrderNum { get; set; }
public string? Remark { get; set; }
public string? ListClass { get; set; }
public string? CssClass { get; set; }

View File

@@ -4,6 +4,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary
{
public class DictionaryGetListOutputDto : EntityDto<Guid>
{
public int OrderNum { get; set; }
public DateTime CreationTime { get; set; } = DateTime.Now;
public Guid? CreatorId { get; set; }
public string? Remark { get; set; }

View File

@@ -4,6 +4,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary
{
public class DictionaryGetOutputDto : EntityDto<Guid>
{
public int OrderNum { get; set; }
public DateTime CreationTime { get; set; } = DateTime.Now;
public Guid? CreatorId { get; set; }
public string? Remark { get; set; }

View File

@@ -2,6 +2,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary
{
public class DictionaryUpdateInputVo
{
public int OrderNum { get; set; }
public string? Remark { get; set; }
public string? ListClass { get; set; }
public string? CssClass { get; set; }

View File

@@ -3,6 +3,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Post
public class PostUpdateInputVo
{
public bool? State { get; set; }
public int OrderNum { get; set; }
public string PostCode { get; set; }
public string PostName { get; set; }
public string? Remark { get; set; }

View File

@@ -6,16 +6,14 @@ using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Quartz;
using Quartz.Logging;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Domain.Repositories;
using Yi.Framework.Rbac.Domain.Shared.Options;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.Rbac.Application.Jobs
{
public class BackupDataBaseJob : QuartzBackgroundWorkerBase
public class BackupDataBaseJob: HangfireBackgroundWorkerBase
{
private ISqlSugarDbContext _dbContext;
private IOptions<RbacOptions> _options;
@@ -24,13 +22,12 @@ namespace Yi.Framework.Rbac.Application.Jobs
_options = options;
_dbContext = dbContext;
JobDetail = JobBuilder.Create<BackupDataBaseJob>().WithIdentity(nameof(BackupDataBaseJob)).Build();
RecurringJobId = "数据库备份";
//每天00点与24点进行备份
Trigger = TriggerBuilder.Create().WithIdentity(nameof(BackupDataBaseJob)).WithCronSchedule("0 0 0,12 * * ? ").Build();
//Trigger = TriggerBuilder.Create().WithIdentity(nameof(BackupDataBaseJob)).WithSimpleSchedule(x=>x.WithIntervalInSeconds(10)).Build();
CronExpression = "0 0 0,12 * * ? ";
}
public override Task Execute(IJobExecutionContext context)
public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
if (_options.Value.EnableDataBaseBackup)
{

View File

@@ -6,7 +6,6 @@ using Yi.Framework.Ddd.Application;
using Yi.Framework.Rbac.Application.Contracts.Dtos.Dictionary;
using Yi.Framework.Rbac.Application.Contracts.IServices;
using Yi.Framework.Rbac.Domain.Entities;
using Yi.Framework.Rbac.Domain.Shared.Consts;
using Yi.Framework.SqlSugarCore.Abstractions;
@@ -15,29 +14,27 @@ namespace Yi.Framework.Rbac.Application.Services
/// <summary>
/// Dictionary服务实现
/// </summary>
public class DictionaryService : YiCrudAppService<DictionaryEntity, DictionaryGetOutputDto,
DictionaryGetListOutputDto, Guid, DictionaryGetListInputVo, DictionaryCreateInputVo,
DictionaryUpdateInputVo>,
IDictionaryService
public class DictionaryService : YiCrudAppService<DictionaryEntity, DictionaryGetOutputDto, DictionaryGetListOutputDto, Guid, DictionaryGetListInputVo, DictionaryCreateInputVo, DictionaryUpdateInputVo>,
IDictionaryService
{
private ISqlSugarRepository<DictionaryEntity, Guid> _repository;
public DictionaryService(ISqlSugarRepository<DictionaryEntity, Guid> repository) : base(repository)
{
_repository = repository;
_repository= repository;
}
/// <summary>
/// 查询
/// </summary>
public override async Task<PagedResultDto<DictionaryGetListOutputDto>> GetListAsync(
DictionaryGetListInputVo input)
public override async Task<PagedResultDto<DictionaryGetListOutputDto>> GetListAsync(DictionaryGetListInputVo input)
{
RefAsync<int> total = 0;
var entities = await _repository._DbQueryable
.WhereIF(input.DictType is not null, x => x.DictType == input.DictType)
.WhereIF(input.DictLabel is not null, x => x.DictLabel!.Contains(input.DictLabel!))
.WhereIF(input.State is not null, x => x.State == input.State)
.OrderByDescending(x => x.OrderNum)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<DictionaryGetListOutputDto>
{
@@ -60,4 +57,4 @@ namespace Yi.Framework.Rbac.Application.Services
return result;
}
}
}
}

View File

@@ -1,220 +0,0 @@
using System.Reflection;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Quartz;
using Quartz.Impl.Matchers;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Timing;
using Yi.Framework.Rbac.Application.Contracts.Dtos.Task;
using Yi.Framework.Rbac.Application.Contracts.IServices;
using Yi.Framework.Rbac.Domain.Shared.Enums;
namespace Yi.Framework.Rbac.Application.Services.Monitor
{
public class TaskService : ApplicationService, ITaskService
{
private readonly ISchedulerFactory _schedulerFactory;
private readonly IClock _clock;
public TaskService(ISchedulerFactory schedulerFactory, IClock clock)
{
_clock = clock;
_schedulerFactory = schedulerFactory;
}
/// <summary>
/// 单查job
/// </summary>
/// <param name="jobId"></param>
/// <returns></returns>
[HttpGet("task/{jobId}")]
public async Task<TaskGetOutput> GetAsync([FromRoute] string jobId)
{
var scheduler = await _schedulerFactory.GetScheduler();
var jobDetail = await scheduler.GetJobDetail(new JobKey(jobId));
var trigger = (await scheduler.GetTriggersOfJob(new JobKey(jobId))).First();
//状态
var state = await scheduler.GetTriggerState(trigger.Key);
var output = new TaskGetOutput
{
JobId = jobDetail.Key.Name,
GroupName = jobDetail.Key.Group,
JobType = jobDetail.JobType.Name,
Properties = Newtonsoft.Json.JsonConvert.SerializeObject(jobDetail.JobDataMap),
Concurrent = !jobDetail.ConcurrentExecutionDisallowed,
Description = jobDetail.Description,
LastRunTime = _clock.Normalize(trigger.GetPreviousFireTimeUtc()?.DateTime ?? DateTime.MinValue),
NextRunTime = _clock.Normalize(trigger.GetNextFireTimeUtc()?.DateTime ?? DateTime.MinValue),
AssemblyName = jobDetail.JobType.Assembly.GetName().Name,
Status = state.ToString()
};
if (trigger is ISimpleTrigger simple)
{
output.TriggerArgs = Math.Round(simple.RepeatInterval.TotalMinutes, 2).ToString() + "分钟";
output.Type = JobTypeEnum.Millisecond;
output.Millisecond = simple.RepeatInterval.TotalMilliseconds;
}
else if (trigger is ICronTrigger cron)
{
output.TriggerArgs = cron.CronExpressionString!;
output.Type = JobTypeEnum.Cron;
output.Cron = cron.CronExpressionString;
}
return output;
}
/// <summary>
/// 多查job
/// </summary>
/// <returns></returns>
public async Task<PagedResultDto<TaskGetListOutput>> GetListAsync([FromQuery] TaskGetListInput input)
{
var items = new List<TaskGetOutput>();
var scheduler = await _schedulerFactory.GetScheduler();
var groups = await scheduler.GetJobGroupNames();
foreach (var groupName in groups)
{
foreach (var jobKey in await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)))
{
string jobName = jobKey.Name;
string jobGroup = jobKey.Group;
var triggers = (await scheduler.GetTriggersOfJob(jobKey)).First();
items.Add(await GetAsync(jobName));
}
}
var output = items.Skip((input.SkipCount - 1) * input.MaxResultCount).Take(input.MaxResultCount)
.OrderByDescending(x => x.LastRunTime)
.ToList();
return new PagedResultDto<TaskGetListOutput>(items.Count(), output.Adapt<List<TaskGetListOutput>>());
}
/// <summary>
/// 创建job
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task CreateAsync(TaskCreateInput input)
{
var scheduler = await _schedulerFactory.GetScheduler();
//设置启动时执行一次,然后最大只执行一次
//jobBuilder
var jobClassType = Assembly.Load(input.AssemblyName).GetTypes().Where(x => x.Name == input.JobType).FirstOrDefault();
if (jobClassType is null)
{
throw new UserFriendlyException($"程序集:{input.AssemblyName}{input.JobType} 不存在");
}
var jobBuilder = JobBuilder.Create(jobClassType).WithIdentity(new JobKey(input.JobId, input.GroupName))
.WithDescription(input.Description);
if (!input.Concurrent)
{
jobBuilder.DisallowConcurrentExecution();
}
//triggerBuilder
TriggerBuilder triggerBuilder = null;
switch (input.Type)
{
case JobTypeEnum.Cron:
triggerBuilder =
TriggerBuilder.Create()
.WithCronSchedule(input.Cron);
break;
case JobTypeEnum.Millisecond:
triggerBuilder =
TriggerBuilder.Create().StartNow()
.WithSimpleSchedule(x => x
.WithInterval(TimeSpan.FromMilliseconds(input.Millisecond ?? 10000))
.RepeatForever()
);
break;
}
//作业计划,单个jobBuilder与多个triggerBuilder组合
await scheduler.ScheduleJob(jobBuilder.Build(), triggerBuilder.Build());
}
/// <summary>
/// 移除job
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task DeleteAsync(IEnumerable<string> id)
{
var scheduler = await _schedulerFactory.GetScheduler();
await scheduler.DeleteJobs(id.Select(x => new JobKey(x)).ToList());
}
/// <summary>
/// 暂停job
/// </summary>
/// <param name="jobId"></param>
/// <returns></returns>
[HttpPut]
public async Task PauseAsync(string jobId)
{
var scheduler = await _schedulerFactory.GetScheduler();
await scheduler.PauseJob(new JobKey(jobId));
}
/// <summary>
/// 开始job
/// </summary>
/// <param name="jobId"></param>
/// <returns></returns>
[HttpPut]
public async Task StartAsync(string jobId)
{
var scheduler = await _schedulerFactory.GetScheduler();
await scheduler.ResumeJob(new JobKey(jobId));
}
/// <summary>
/// 更新job
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <returns></returns>
public async Task UpdateAsync(string id, TaskUpdateInput input)
{
await DeleteAsync(new List<string>() { id });
await CreateAsync(input.Adapt<TaskCreateInput>());
}
[HttpPost("task/run-once/{id}")]
public async Task RunOnceAsync([FromRoute] string id)
{
var scheduler = await _schedulerFactory.GetScheduler();
var jobDetail = await scheduler.GetJobDetail(new JobKey(id));
var jobBuilder = JobBuilder.Create(jobDetail.JobType).WithIdentity(new JobKey(Guid.NewGuid().ToString()));
//设置启动时执行一次,然后最大只执行一次
var trigger = TriggerBuilder.Create().WithIdentity(Guid.NewGuid().ToString()).StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInHours(1)
.WithRepeatCount(1))
.Build();
await scheduler.ScheduleJob(jobBuilder.Build(), trigger);
}
}
}

View File

@@ -30,6 +30,7 @@ namespace Yi.Framework.Rbac.Application.Services.System
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.PostName),
x => x.PostName.Contains(input.PostName!))
.WhereIF(input.State is not null, x => x.State == input.State)
.OrderByDescending(x => x.OrderNum)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<PostGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
}

View File

@@ -10,13 +10,15 @@
<ItemGroup>
<PackageReference Include="Lazy.Captcha.Core" Version="2.0.7" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.7" />
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.BackgroundJobs.Hangfire" Version="$(AbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj" />
<ProjectReference Include="..\Yi.Framework.Rbac.Application.Contracts\Yi.Framework.Rbac.Application.Contracts.csproj" />
<ProjectReference Include="..\Yi.Framework.Rbac.Domain\Yi.Framework.Rbac.Domain.csproj" />
<ProjectReference Include="..\..\..\framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using Lazy.Captcha.Core.Generator;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Modularity;
using Yi.Framework.Ddd.Application;
using Yi.Framework.Rbac.Application.Contracts;
@@ -15,8 +16,7 @@ namespace Yi.Framework.Rbac.Application
typeof(YiFrameworkRbacDomainModule),
typeof(YiFrameworkDddApplicationModule),
typeof(AbpBackgroundWorkersQuartzModule)
typeof(YiFrameworkDddApplicationModule)
)]
public class YiFrameworkRbacApplicationModule : AbpModule
{
@@ -24,7 +24,10 @@ namespace Yi.Framework.Rbac.Application
{
var service = context.Services;
service.AddCaptcha();
service.AddCaptcha(options =>
{
options.CaptchaType = CaptchaType.ARITHMETIC;
});
}
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)

View File

@@ -19,7 +19,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
public async Task SeedAsync(DataSeedContext context)
{
if (!await _repository.IsAnyAsync(x => x.MenuName == "系统管理"&&x.MenuSource==MenuSourceEnum.Pure))
if (!await _repository.IsAnyAsync(x => x.MenuName == "系统管理" && x.MenuSource == MenuSourceEnum.Pure))
{
await _repository.InsertManyAsync(GetSeedData());
}
@@ -37,7 +37,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
OrderNum = 100
};
entities.Add(system);
//系统监控
MenuAggregateRoot monitoring = new MenuAggregateRoot(_guidGenerator.Create())
{
@@ -64,7 +64,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
};
entities.Add(online);
//Yi框架
MenuAggregateRoot guide = new MenuAggregateRoot(_guidGenerator.Create())
{
@@ -77,7 +77,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
Component = null
};
entities.Add(guide);
//用户管理
MenuAggregateRoot user = new MenuAggregateRoot(_guidGenerator.Create())
{
@@ -141,7 +141,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
entities.Add(userRemove);
MenuAggregateRoot userResetPwd = new MenuAggregateRoot(_guidGenerator.Create())
MenuAggregateRoot userResetPwd = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "重置密码",
@@ -408,7 +408,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
IsDeleted = false
};
entities.Add(postRemove);
//操作日志
MenuAggregateRoot operationLog = new MenuAggregateRoot(_guidGenerator.Create())
@@ -491,10 +491,78 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
OrderNum = 100,
ParentId = loginLog.Id,
IsDeleted = false,
};
entities.Add(loginLogRemove);
//参数设置
MenuAggregateRoot config = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "参数设置",
PermissionCode = "system:config:list",
MenuType = MenuTypeEnum.Menu,
Router = "config",
IsShow = true,
IsLink = false,
IsCache = true,
Component = "/system/config/index",
MenuIcon = "ri:edit-box-line",
OrderNum = 94,
ParentId = system.Id,
IsDeleted = false
};
entities.Add(config);
MenuAggregateRoot configQuery = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "参数查询",
PermissionCode = "system:config:query",
MenuType = MenuTypeEnum.Component,
OrderNum = 100,
ParentId = config.Id,
IsDeleted = false
};
entities.Add(configQuery);
MenuAggregateRoot configAdd = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "参数新增",
PermissionCode = "system:config:add",
MenuType = MenuTypeEnum.Component,
OrderNum = 100,
ParentId = config.Id,
IsDeleted = false
};
entities.Add(configAdd);
MenuAggregateRoot configEdit = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "参数修改",
PermissionCode = "system:config:edit",
MenuType = MenuTypeEnum.Component,
OrderNum = 100,
ParentId = config.Id,
IsDeleted = false
};
entities.Add(configEdit);
MenuAggregateRoot configRemove = new MenuAggregateRoot(_guidGenerator.Create())
{
MenuName = "参数删除",
PermissionCode = "system:config:remove",
MenuType = MenuTypeEnum.Component,
OrderNum = 100,
ParentId = config.Id,
IsDeleted = false
};
entities.Add(configRemove);
//默认值
entities.ForEach(m =>
{

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.TenantManagement.Domain.Shared
{
public class TenantConst
{
public static string TenantDbDefaultName = "Master";
}
}

View File

@@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="8.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,11 +0,0 @@
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement;
namespace YiFrameworkTenantManagementDomain.Shared
{
[DependsOn(typeof(AbpTenantManagementDomainSharedModule))]
public class YiFrameworkTenantManagementDomainSharedModule : AbpModule
{
}
}

View File

@@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.Ddd.Application.Contracts\Yi.Framework.Ddd.Application.Contracts.csproj" />
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.Application.Contracts\Yi.Framework.Bbs.Application.Contracts.csproj" />
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.Application.Contracts\Yi.Framework.Rbac.Application.Contracts.csproj" />
<ProjectReference Include="..\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,24 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Acme.BookStore.Domain.Shared.Enums;
namespace Acme.BookStore.Application.Contracts.Dtos.Book
{
public class BookCreateUpdateDto
{
[Required]
[StringLength(128)]
public string Name { get; set; }
[Required]
public BookTypeEnum Type { get; set; } = BookTypeEnum.Undefined;
[Required]
[DataType(DataType.Date)]
public DateTime PublishDate { get; set; } = DateTime.Now;
[Required]
public float Price { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
using Acme.BookStore.Domain.Shared.Enums;
using Volo.Abp.Application.Dtos;
namespace Acme.BookStore.Application.Contracts.Dtos.Book
{
public class BookDto : AuditedEntityDto<Guid>
{
public string Name { get; set; }
public BookTypeEnum Type { get; set; }
public DateTime PublishDate { get; set; }
public float Price { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
using Acme.BookStore.Application.Contracts.Dtos.Book;
using Volo.Abp.Application.Dtos;
using Yi.Framework.Ddd.Application.Contracts;
namespace Acme.BookStore.Application.Contracts.IServices
{
public interface IBookAppService :
IYiCrudAppService< //Defines CRUD methods
BookDto, //Used to show books
Guid, //Primary key of the book entity
PagedAndSortedResultRequestDto, //Used for paging/sorting
BookCreateUpdateDto> //Used to create/update a book
{
}
}

View File

@@ -1,20 +0,0 @@
using Volo.Abp.Modularity;
using Acme.BookStore.Domain.Shared;
using Yi.Framework.Bbs.Application.Contracts;
using Yi.Framework.Ddd.Application.Contracts;
using Yi.Framework.Rbac.Application.Contracts;
namespace Acme.BookStore.Application.Contracts
{
[DependsOn(
typeof(YiAbpDomainSharedModule),
typeof(YiFrameworkRbacApplicationContractsModule),
typeof(YiFrameworkBbsApplicationContractsModule),
typeof(YiFrameworkDddApplicationContractsModule))]
public class YiAbpApplicationContractsModule:AbpModule
{
}
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj" />
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.Application\Yi.Framework.Bbs.Application.csproj" />
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.Application\Yi.Framework.Rbac.Application.csproj" />
<ProjectReference Include="..\Acme.BookStore.Application.Contracts\Acme.BookStore.Application.Contracts.csproj" />
<ProjectReference Include="..\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Jobs\" />
</ItemGroup>
</Project>

View File

@@ -1,36 +0,0 @@
using Quartz;
using SqlSugar;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using Yi.Framework.Rbac.Domain.Entities;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Acme.BookStore.Application.Jobs
{
/// <summary>
/// 定时任务
/// </summary>
public class TestJob : QuartzBackgroundWorkerBase
{
private ISqlSugarRepository<UserAggregateRoot> _repository;
public TestJob(ISqlSugarRepository<UserAggregateRoot> repository)
{
_repository = repository;
JobDetail = JobBuilder.Create<TestJob>().WithIdentity(nameof(TestJob)).Build();
Trigger = TriggerBuilder.Create().WithIdentity(nameof(TestJob)).StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1000 * 60)
.RepeatForever())
.Build();
}
public override async Task Execute(IJobExecutionContext context)
{
//定时任务,非常简单
Console.WriteLine("你好,世界");
// var eneities= await _repository.GetListAsync();
//var entities= await _sqlSugarClient.Queryable<UserEntity>().ToListAsync();
//await Console.Out.WriteLineAsync(entities.Count().ToString());
}
}
}

View File

@@ -1,42 +0,0 @@
using Acme.BookStore.Application.Contracts.Dtos.Book;
using Acme.BookStore.Application.Contracts.IServices;
using Acme.BookStore.Domain.Entities;
using SqlSugar;
using Volo.Abp.Application.Dtos;
using Yi.Framework.Ddd.Application;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Acme.BookStore.Application.Services
{
public class BookAppService :
YiCrudAppService<
BookAggregateRoot, //The Book entity
BookDto, //Used to show books
Guid, //Primary key of the book entity
PagedAndSortedResultRequestDto, //Used for paging/sorting
BookCreateUpdateDto>, //Used to create/update a book
IBookAppService //implement the IBookAppService
{
private ISqlSugarRepository<BookAggregateRoot, Guid> _repository;
public BookAppService(ISqlSugarRepository<BookAggregateRoot, Guid> repository)
: base(repository)
{
_repository = repository;
}
public override async Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input)
{
{
RefAsync<int> total = 0;
//由于直接查询接口基本上都是有包含查询条件的,默认内置的查询接口将无法满足业务的需求,所以基本上多查询都是有进行重写的
var entities = await _repository._DbQueryable
//.WhereIF(!string.IsNullOrEmpty(input.ConfigKey), x => x.ConfigKey.Contains(input.ConfigKey!))
// .WhereIF(!string.IsNullOrEmpty(input.ConfigName), x => x.ConfigName!.Contains(input.ConfigName!))
// .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<BookDto>(total, await MapToGetListOutputDtosAsync(entities));
}
}
}
}

View File

@@ -1,18 +0,0 @@
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
namespace Acme.BookStore.Application.Services
{
public class TestService : ApplicationService
{
/// <summary>
/// 你好世界
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string GetHelloWorld(string? name)
{
return name ?? "HelloWord";
}
}
}

View File

@@ -1,23 +0,0 @@
using Volo.Abp.Modularity;
using Acme.BookStore.Application.Contracts;
using Acme.BookStore.Domain;
using Yi.Framework.Bbs.Application;
using Yi.Framework.Ddd.Application;
using Yi.Framework.Rbac.Application;
namespace Acme.BookStore.Application
{
[DependsOn(
typeof(YiAbpApplicationContractsModule),
typeof(YiAbpDomainModule),
typeof(YiFrameworkRbacApplicationModule),
typeof(YiFrameworkBbsApplicationModule),
typeof(YiFrameworkDddApplicationModule)
)]
public class YiAbpApplicationModule : AbpModule
{
}
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="$(AbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.Domain.Shared\Yi.Framework.Bbs.Domain.Shared.csproj" />
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.Domain.Shared\Yi.Framework.Rbac.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Consts\" />
<Folder Include="Dtos\" />
<Folder Include="Etos\" />
</ItemGroup>
</Project>

View File

@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Acme.BookStore.Domain.Shared.Enums
{
public enum BookTypeEnum
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
}

View File

@@ -1,17 +0,0 @@
using Volo.Abp.Domain;
using Volo.Abp.Modularity;
using Yi.Framework.Bbs.Domain.Shared;
using Yi.Framework.Rbac.Domain.Shared;
namespace Acme.BookStore.Domain.Shared
{
[DependsOn(
typeof(YiFrameworkRbacDomainSharedModule),
typeof(YiFrameworkBbsDomainSharedModule),
typeof(AbpDddDomainSharedModule))]
public class YiAbpDomainSharedModule : AbpModule
{
}
}

View File

@@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Caching" Version="$(AbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
<ProjectReference Include="..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.Domain\Yi.Framework.Bbs.Domain.csproj" />
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.Domain\Yi.Framework.Rbac.Domain.csproj" />
<ProjectReference Include="..\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Managers\" />
<Folder Include="Repositories\" />
<Folder Include="EventHandlers\" />
</ItemGroup>
</Project>

View File

@@ -1,24 +0,0 @@
using Acme.BookStore.Domain.Shared.Enums;
using SqlSugar;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities.Auditing;
namespace Acme.BookStore.Domain.Entities
{
[SugarTable("Book")]
public class BookAggregateRoot : AuditedAggregateRoot<Guid>
{
[SugarColumn(IsPrimaryKey = true)]
public override Guid Id { get; protected set; }
public string Name { get; set; }
public BookTypeEnum Type { get; set; }
public DateTime PublishDate { get; set; }
public float Price { get; set; }
[SugarColumn(IsIgnore = true)]
public override ExtraPropertyDictionary ExtraProperties { get; protected set; }
}
}

View File

@@ -1,26 +0,0 @@
using Volo.Abp.Caching;
using Volo.Abp.Domain;
using Volo.Abp.Modularity;
using Acme.BookStore.Domain.Shared;
using Yi.Framework.Bbs.Domain;
using Yi.Framework.Mapster;
using Yi.Framework.Rbac.Domain;
namespace Acme.BookStore.Domain
{
[DependsOn(
typeof(YiAbpDomainSharedModule),
typeof(YiFrameworkRbacDomainModule),
typeof(YiFrameworkBbsDomainModule),
typeof(YiFrameworkMapsterModule),
typeof(AbpDddDomainModule),
typeof(AbpCachingModule)
)]
public class YiAbpDomainModule : AbpModule
{
}
}

View File

@@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
<ProjectReference Include="..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.SqlSugarCore\Yi.Framework.Bbs.SqlSugarCore.csproj" />
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.SqlSugarCore\Yi.Framework.Rbac.SqlSugarCore.csproj" />
<ProjectReference Include="..\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Repositories\" />
</ItemGroup>
</Project>

View File

@@ -1,50 +0,0 @@
using Acme.BookStore.Domain.Entities;
using Acme.BookStore.Domain.Shared.Enums;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Acme.BookStore.SqlSugarCore.DataSeeds
{
public class BookStoreDataSeed : IDataSeedContributor, ITransientDependency
{
private ISqlSugarRepository<BookAggregateRoot> _bookRepository;
private IGuidGenerator _guidGenerator;
public BookStoreDataSeed(ISqlSugarRepository<BookAggregateRoot> repository, IGuidGenerator guidGenerator)
{
_bookRepository = repository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
if (!await _bookRepository.IsAnyAsync(x => true))
{
await _bookRepository.InsertAsync(
new BookAggregateRoot
{
Name = "1984",
Type = BookTypeEnum.Dystopia,
PublishDate = new DateTime(1949, 6, 8),
Price = 19.84f
},
autoSave: true
);
await _bookRepository.InsertAsync(
new BookAggregateRoot
{
Name = "The Hitchhiker's Guide to the Galaxy",
Type = BookTypeEnum.ScienceFiction,
PublishDate = new DateTime(1995, 9, 27),
Price = 42.0f
},
autoSave: true
);
}
}
}
}

View File

@@ -1,31 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Acme.BookStore.Domain;
using Acme.BookStore.SqlSugarCore;
using Yi.Framework.Bbs.SqlSugarCore;
using Yi.Framework.Mapster;
using Yi.Framework.Rbac.SqlSugarCore;
using Yi.Framework.SqlSugarCore;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Acme.BookStore.SqlsugarCore
{
[DependsOn(
typeof(YiAbpDomainModule),
typeof(YiFrameworkRbacSqlSugarCoreModule),
typeof(YiFrameworkBbsSqlSugarCoreModule),
typeof(YiFrameworkMapsterModule),
typeof(YiFrameworkSqlSugarCoreModule)
)]
public class YiAbpSqlSugarCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddYiDbContext<YiDbContext>();
//默认不开放可根据项目需要是否Db直接对外开放
//context.Services.AddTransient(x => x.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient);
}
}
}

View File

@@ -1,14 +0,0 @@
using Microsoft.Extensions.Logging;
using SqlSugar;
using Volo.Abp.DependencyInjection;
using Yi.Framework.Rbac.SqlSugarCore;
namespace Acme.BookStore.SqlSugarCore
{
public class YiDbContext : YiRbacDbContext
{
public YiDbContext(IAbpLazyServiceProvider lazyServiceProvider) : base(lazyServiceProvider)
{
}
}
}

View File

@@ -1,43 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\common.props" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.AspNetCore.Authentication.OAuth\Yi.Framework.AspNetCore.Authentication.OAuth.csproj" />
<ProjectReference Include="..\..\framework\Yi.Framework.AspNetCore\Yi.Framework.AspNetCore.csproj" />
<ProjectReference Include="..\Acme.BookStore.Application\Acme.BookStore.Application.csproj" />
<ProjectReference Include="..\Acme.BookStore.SqlSugarCore\Acme.BookStore.SqlSugarCore.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\icon\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="ip2region.db">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="database_backup\" />
</ItemGroup>
</Project>

View File

@@ -1,37 +0,0 @@
using Serilog;
using Serilog.Events;
using Acme.BookStore.Web;
//创建日志,可使用{SourceContext}记录
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.AspNetCore.Hosting.Diagnostics", LogEventLevel.Error)
.MinimumLevel.Override("Quartz", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File("logs/all/log-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug))
.WriteTo.Async(c => c.File("logs/error/errorlog-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error))
.WriteTo.Async(c => c.Console(restrictedToMinimumLevel: LogEventLevel.Information))
.CreateLogger();
try
{
Log.Information("Yi框架-Abp.vNext启动");
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls(builder.Configuration["App:SelfUrl"]);
builder.Host.UseAutofac();
builder.Host.UseSerilog();
await builder.Services.AddApplicationAsync<YiAbpWebModule>();
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Yi框架-Abp.vNext爆炸");
}
finally
{
Log.CloseAndFlush();
}

View File

@@ -1,15 +0,0 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"Acme.BookStore.Web": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:19001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -1,198 +0,0 @@
using System.Text;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Converters;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Acme.BookStore.Application;
using Acme.BookStore.SqlsugarCore;
using Yi.Framework.AspNetCore;
using Yi.Framework.AspNetCore.Authentication.OAuth;
using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
using Yi.Framework.Bbs.Application;
using Yi.Framework.Rbac.Application;
using Yi.Framework.Rbac.Domain.Shared.Options;
namespace Acme.BookStore.Web
{
[DependsOn(
typeof(YiAbpSqlSugarCoreModule),
typeof(YiAbpApplicationModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAuditingModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(YiFrameworkAspNetCoreModule),
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
)]
public class YiAbpWebModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var host = context.Services.GetHostingEnvironment();
var service = context.Services;
//请求日志
Configure<AbpAuditingOptions>(optios =>
{
optios.IsEnabled = true;
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
});
//动态Api
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly, options => options.RemoteServiceName = "default");
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly, options => options.RemoteServiceName = "rbac");
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly, options => options.RemoteServiceName = "bbs");
});
//设置api格式
service.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});
Configure<AbpAntiForgeryOptions>(options =>
{
options.AutoValidate = false;
});
//Swagger
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
{
options.SwaggerDoc("default", new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
});
//跨域
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]!
.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
//jwt鉴权
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
})
.AddQQ(options =>
{
configuration.GetSection("OAuth:QQ").Bind(options);
})
.AddGitee(options =>
{
configuration.GetSection("OAuth:Gitee").Bind(options);
});
//授权
context.Services.AddAuthorization();
return Task.CompletedTask;
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var service = context.ServiceProvider;
var env = context.GetEnvironment();
var app = context.GetApplicationBuilder();
app.UseRouting();
//跨域
app.UseCors(DefaultCorsPolicyName);
//鉴权
app.UseAuthentication();
//swagger
app.UseYiSwagger();
//请求处理
app.UseYiApiHandlinge();
//静态资源
app.UseStaticFiles("/api/app/wwwroot");
app.UseDefaultFiles();
app.UseDirectoryBrowser("/api/app/wwwroot");
//工作单元
app.UseUnitOfWork();
//授权
app.UseAuthorization();
//审计日志
app.UseAuditing();
//日志记录
app.UseAbpSerilogEnrichers();
//终节点
app.UseConfiguredEndpoints();
return Task.CompletedTask;
}
}
}

View File

@@ -1,73 +0,0 @@
{
"Logging": {
"LogLevel": {
//"Default": "Information",
"Default": "Debug",
"Microsoft.AspNetCore": "Warning"
}
},
//应用启动
"App": {
"SelfUrl": "http://*:19001",
"CorsOrigins": "http://localhost:19001;http://localhost:18000"
},
//数据库类型列表
"DbList": [ "Sqlite", "Mysql", "Sqlserver", "Oracle", "PostgreSQL" ],
"DbConnOptions": {
"Url": "DataSource=yi-abp-dev.db",
"DbType": "Sqlite",
"EnabledReadWrite": false,
"EnabledCodeFirst": true,
"EnabledSqlLog": true,
"EnabledDbSeed": true,
"EnableUnderLine": false // 启用驼峰转下划线
//读写分离地址
//"ReadUrl": [
// "DataSource=[xxxx]", //Sqlite
// "server=[xxxx];port=3306;database=[xxxx];user id=[xxxx];password=[xxxx]", //Mysql
// "Data Source=[xxxx];Initial Catalog=[xxxx];User ID=[xxxx];password=[xxxx]" //Sqlserver
// "HOST=[xxxx];PORT=5432;DATABASE=[xxxx];USERID=[xxxx];PASSWORD=[xxxx]" //PostgreSQL
//]
},
//鉴权
"JwtOptions": {
"Issuer": "https://ccnetcore.com",
"Audience": "https://ccnetcore.com",
"SecurityKey": "zqxwcevrbtnymu312412ihe9rfwhe78rh23djoi32hrui3ryf9e8wfh34iuj54y0934uti4h97fgw7hf97wyh8yy69520",
"ExpiresMinuteTime": 86400
},
//第三方登录
"OAuth": {
//QQ
"QQ": {
"ClientId": "",
"ClientSecret": "",
"RedirectUri": ""
},
//码云
"Gitee": {
"ClientId": "",
"ClientSecret": "",
"RedirectUri": ""
}
},
//Rbac模块
"RbacOptions": {
//超级管理员种子数据默认密码
"AdminPassword": "123456",
//是否开启验证码验证
"EnableCaptcha": true,
//是否开启注册功能
"EnableRegister": false,
//开启定时数据库备份
"EnableDataBaseBackup": false
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -1,15 +1,13 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Logging;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Data;
using Yi.Framework.Rbac.Domain.Entities;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Abp.Application.Jobs
{
public class DemoResetJob : QuartzBackgroundWorkerBase
public class DemoResetJob : HangfireBackgroundWorkerBase
{
private ISqlSugarDbContext _dbContext;
private ILogger<DemoResetJob> _logger => LoggerFactory.CreateLogger<DemoResetJob>();
@@ -18,15 +16,15 @@ namespace Yi.Abp.Application.Jobs
public DemoResetJob(ISqlSugarDbContext dbContext, IDataSeeder dataSeeder, IConfiguration configuration)
{
_dbContext = dbContext;
JobDetail = JobBuilder.Create<DemoResetJob>().WithIdentity(nameof(DemoResetJob)).Build();
//每天01点与13点,演示环境进行重置
Trigger = TriggerBuilder.Create().WithIdentity(nameof(DemoResetJob)).WithCronSchedule("0 0 1,13 * * ? ").Build();
// Trigger = TriggerBuilder.Create().WithIdentity(nameof(DemoResetJob)).WithSimpleSchedule(x=>x.WithIntervalInSeconds(10)).Build();
RecurringJobId = "重置demo环境";
//每天1点和13点进行重置demo环境
CronExpression = "0 0 1,13 * * ?";
_dataSeeder = dataSeeder;
_configuration = configuration;
}
public override async Task Execute(IJobExecutionContext context)
public override async Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
//开启演示环境重置功能
if (_configuration.GetSection("EnableDemoReset").Get<bool>())
@@ -50,7 +48,6 @@ namespace Yi.Abp.Application.Jobs
}
}
}
}

View File

@@ -1,6 +1,6 @@
using Quartz;
using Hangfire;
using SqlSugar;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using Yi.Framework.Rbac.Domain.Entities;
@@ -11,26 +11,21 @@ namespace Yi.Abp.Application.Jobs
/// <summary>
/// 定时任务
/// </summary>
public class TestJob : QuartzBackgroundWorkerBase
public class TestJob : HangfireBackgroundWorkerBase
{
private ISqlSugarRepository<UserAggregateRoot> _repository;
public TestJob(ISqlSugarRepository<UserAggregateRoot> repository)
{
_repository = repository;
JobDetail = JobBuilder.Create<TestJob>().WithIdentity(nameof(TestJob)).Build();
Trigger = TriggerBuilder.Create().WithIdentity(nameof(TestJob)).StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1000 * 60)
.RepeatForever())
.Build();
RecurringJobId = "测试";
//每天一次
CronExpression = Cron.Daily();
}
public override async Task Execute(IJobExecutionContext context)
public override Task DoWorkAsync(CancellationToken cancellationToken = new CancellationToken())
{
//定时任务,非常简单
Console.WriteLine("你好,世界");
// var eneities= await _repository.GetListAsync();
//var entities= await _sqlSugarClient.Queryable<UserEntity>().ToListAsync();
//await Console.Out.WriteLineAsync(entities.Count().ToString());
return Task.CompletedTask;
}
}
}

View File

@@ -3,6 +3,7 @@
<ItemGroup>
<ProjectReference Include="..\..\framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj" />
<ProjectReference Include="..\..\framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj" />
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.Application\Yi.Framework.Bbs.Application.csproj" />
<ProjectReference Include="..\..\module\chat-hub\Yi.Framework.ChatHub.Application\Yi.Framework.ChatHub.Application.csproj" />

View File

@@ -1,6 +1,7 @@
using Volo.Abp.SettingManagement;
using Yi.Abp.Application.Contracts;
using Yi.Abp.Domain;
using Yi.Framework.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Application;
using Yi.Framework.ChatHub.Application;
using Yi.Framework.CodeGen.Application;
@@ -23,7 +24,8 @@ namespace Yi.Abp.Application
typeof(YiFrameworkCodeGenApplicationModule),
typeof (YiFrameworkSettingManagementApplicationModule),
typeof(YiFrameworkDddApplicationModule)
typeof(YiFrameworkDddApplicationModule),
typeof(YiFrameworkBackgroundWorkersHangfireModule)
)]
public class YiAbpApplicationModule : AbpModule
{

View File

@@ -8,6 +8,8 @@
<ItemGroup>
<PackageReference Include="Hangfire.MemoryStorage" Version="1.8.1.1" />
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.3" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />

View File

@@ -1,22 +1,29 @@
using System.Globalization;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Threading.RateLimiting;
using Hangfire;
using Hangfire.MemoryStorage;
using Hangfire.Redis.StackExchange;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Converters;
using StackExchange.Redis;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs.Hangfire;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Swashbuckle;
@@ -28,11 +35,12 @@ using Yi.Framework.AspNetCore.Authentication.OAuth.Gitee;
using Yi.Framework.AspNetCore.Authentication.OAuth.QQ;
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder;
using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection;
using Yi.Framework.AspNetCore.UnifyResult;
using Yi.Framework.BackgroundWorkers.Hangfire;
using Yi.Framework.Bbs.Application;
using Yi.Framework.Bbs.Application.Extensions;
using Yi.Framework.ChatHub.Application;
using Yi.Framework.CodeGen.Application;
using Yi.Framework.Core.Json;
using Yi.Framework.Rbac.Application;
using Yi.Framework.Rbac.Domain.Authorization;
using Yi.Framework.Rbac.Domain.Shared.Consts;
@@ -50,6 +58,8 @@ namespace Yi.Abp.Web
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAuditingModule),
typeof(YiFrameworkBackgroundWorkersHangfireModule),
typeof(AbpBackgroundJobsHangfireModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(YiFrameworkAspNetCoreModule),
typeof(YiFrameworkAspNetCoreAuthenticationOAuthModule)
@@ -63,212 +73,247 @@ namespace Yi.Abp.Web
var configuration = context.Services.GetConfiguration();
var host = context.Services.GetHostingEnvironment();
var service = context.Services;
//请求日志
Configure<AbpAuditingOptions>(optios =>
{
//默认关闭,开启会有大量的审计日志
optios.IsEnabled = false;
//审计日志过滤器
optios.AlwaysLogSelectors.Add(x => Task.FromResult(true));
optios.IsEnabled = true;
});
//忽略审计日志路径
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
options.IgnoredUrls.Add("/api/app/file/");
options.IgnoredUrls.Add("/hangfire");
});
//采用furion格式的规范化api默认不开启使用abp优雅的方式
//你没看错。。。
//service.AddFurionUnifyResultApi();
//你没看错。。。
//service.AddFurionUnifyResultApi();
//配置错误处理显示详情
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
//配置错误处理显示详情
Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
//动态Api
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly,
options => options.RemoteServiceName = "default");
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly,
options => options.RemoteServiceName = "rbac");
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly,
options => options.RemoteServiceName = "bbs");
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly,
options => options.RemoteServiceName = "chat-hub");
options.ConventionalControllers.Create(typeof(YiFrameworkTenantManagementApplicationModule).Assembly,
options => options.RemoteServiceName = "tenant-management");
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly,
options => options.RemoteServiceName = "code-gen");
//统一前缀
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
});
//设置api格式
service.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});
//设置缓存不要过期默认滑动20分钟
Configure<AbpDistributedCacheOptions>(cacheOptions =>
{
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
//缓存key前缀
cacheOptions.KeyPrefix = "Yi:";
});
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; });
//Swagger
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
{
options.SwaggerDoc("default",
new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
});
//跨域
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
//动态Api
Configure<AbpAspNetCoreMvcOptions>(options =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]!
.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly,
options => options.RemoteServiceName = "default");
options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly,
options => options.RemoteServiceName = "rbac");
options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly,
options => options.RemoteServiceName = "bbs");
options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly,
options => options.RemoteServiceName = "chat-hub");
options.ConventionalControllers.Create(
typeof(YiFrameworkTenantManagementApplicationModule).Assembly,
options => options.RemoteServiceName = "tenant-management");
options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly,
options => options.RemoteServiceName = "code-gen");
//统一前缀
options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app");
});
});
//配置多租户
Configure<AbpTenantResolveOptions>(options =>
{
//基于cookie jwt不好用有坑
options.TenantResolvers.Clear();
options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new CookieTenantResolveContributor());
//【NewtonsoftJson严重问题逆天】设置api格式留给后人铭记
// service.AddControllers().AddNewtonsoftJson(options =>
// {
// options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
// options.SerializerSettings.Converters.Add(new StringEnumConverter());
// });
//options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
});
//速率限制
//每60秒限制100个请求滑块添加分6段
service.AddRateLimiter(_ =>
{
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
_.OnRejected = (context, _) =>
//请使用微软的注意abp date又包了一层采用DefaultJsonTypeInfoResolver统一覆盖
Configure<JsonOptions>(options =>
{
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter());
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
//设置缓存不要过期默认滑动20分钟
Configure<AbpDistributedCacheOptions>(cacheOptions =>
{
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
//缓存key前缀
cacheOptions.KeyPrefix = "Yi:";
});
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; });
//Swagger
context.Services.AddYiSwaggerGen<YiAbpWebModule>(options =>
{
options.SwaggerDoc("default",
new OpenApiInfo { Title = "Yi.Framework.Abp", Version = "v1", Description = "集大成者" });
});
//跨域
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
context.HttpContext.Response.Headers.RetryAfter =
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
builder
.WithOrigins(
configuration["App:CorsOrigins"]!
.Split(";", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
//配置多租户
Configure<AbpTenantResolveOptions>(options =>
{
//基于cookie jwt不好用有坑
options.TenantResolvers.Clear();
options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new HeaderTenantResolveContributor());
//options.TenantResolvers.Add(new CookieTenantResolveContributor());
//options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
});
//配置Hangfire定时任务存储开启redis后优先使用redis
var redisConfiguration = configuration["Redis:Configuration"];
var redisEnabled = configuration["Redis:IsEnabled"];
context.Services.AddHangfire(config =>
{
if (redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled))
{
config.UseRedisStorage(
ConnectionMultiplexer.Connect(redisConfiguration),
new RedisStorageOptions()
{
InvisibilityTimeout = TimeSpan.FromHours(1), //JOB允许执行1小时
Prefix = "Yi:HangfireJob:"
}).WithJobExpirationTimeout(TimeSpan.FromHours(1));
}
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
return new ValueTask();
};
//全局使用,链式表达式
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
else
{
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
config.UseMemoryStorage();
}
});
return RateLimitPartition.GetSlidingWindowLimiter
(userAgent, _ =>
new SlidingWindowRateLimiterOptions
{
PermitLimit = 1000,
Window = TimeSpan.FromSeconds(60),
SegmentsPerWindow = 6,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});
}));
});
//jwt鉴权
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
//速率限制
//每60秒限制100个请求滑块添加分6段
service.AddRateLimiter(_ =>
{
options.TokenValidationParameters = new TokenValidationParameters
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
_.OnRejected = (context, _) =>
{
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
{
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken))
{
context.Token = accessToken;
}
return Task.CompletedTask;
context.HttpContext.Response.Headers.RetryAfter =
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
}
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
return new ValueTask();
};
})
.AddJwtBearer(TokenTypeConst.Refresh, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = refreshJwtOptions.Issuer,
ValidAudience = refreshJwtOptions.Audience,
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
//全局使用,链式表达式
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
{
var refresh_token = context.Request.Headers["refresh_token"];
if (!string.IsNullOrEmpty(refresh_token))
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
return RateLimitPartition.GetSlidingWindowLimiter
(userAgent, _ =>
new SlidingWindowRateLimiterOptions
{
PermitLimit = 1000,
Window = TimeSpan.FromSeconds(60),
SegmentsPerWindow = 6,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});
}));
});
//jwt鉴权
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = refresh_token;
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
var refreshToken = context.Request.Query["refresh_token"];
if (!string.IsNullOrEmpty(refreshToken))
};
})
.AddJwtBearer(TokenTypeConst.Refresh, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero,
ValidateIssuerSigningKey = true,
ValidIssuer = refreshJwtOptions.Issuer,
ValidAudience = refreshJwtOptions.Audience,
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = refreshToken;
var refresh_token = context.Request.Headers["refresh_token"];
if (!string.IsNullOrEmpty(refresh_token))
{
context.Token = refresh_token;
return Task.CompletedTask;
}
var refreshToken = context.Request.Query["refresh_token"];
if (!string.IsNullOrEmpty(refreshToken))
{
context.Token = refreshToken;
}
return Task.CompletedTask;
}
};
})
.AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
.AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
return Task.CompletedTask;
}
};
})
.AddQQ(options => { configuration.GetSection("OAuth:QQ").Bind(options); })
.AddGitee(options => { configuration.GetSection("OAuth:Gitee").Bind(options); });
//授权
context.Services.AddAuthorization();
//授权
context.Services.AddAuthorization();
return Task.CompletedTask;
}
return Task.CompletedTask;
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var service = context.ServiceProvider;
var env = context.GetEnvironment();
var app = context.GetApplicationBuilder();
@@ -320,11 +365,15 @@ namespace Yi.Abp.Web
//日志记录
app.UseAbpSerilogEnrichers();
//Hangfire定时任务面板可配置授权
app.UseAbpHangfireDashboard("/hangfire", options =>
{
// options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() };
});
//终节点
app.UseConfiguredEndpoints();
return Task.CompletedTask;
}
}
}

View File

@@ -2,8 +2,6 @@
using Volo.Abp.Auditing;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.BackgroundWorkers.Quartz;
using Volo.Abp.Domain.Repositories;
using Yi.Framework.Rbac.Application;
using Yi.Framework.Rbac.Domain.Entities;
using Yi.Framework.Rbac.Domain.Managers;
@@ -24,10 +22,11 @@ namespace Yi.Framework.Rbac.Test
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBackgroundWorkerQuartzOptions>(options =>
{
options.IsAutoRegisterEnabled = false;
});
// Configure<AbpBackgroundWorkerQuartzOptions>(options =>
// {
// options.IsAutoRegisterEnabled = false;
// });
Configure<AbpBackgroundWorkerOptions> (options =>
{
options.IsEnabled = false; //禁用作业执行
@@ -35,7 +34,6 @@ namespace Yi.Framework.Rbac.Test
Configure<DbConnOptions>(options =>
{
options.Url = $"DataSource=yi-rbac-test-{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.db";
});
}

View File

@@ -14,6 +14,10 @@ namespace Yi.Abp.Tool.Application.Contracts.Dtos
/// </summary>
public string Name { get; set; }
/// <summary>
/// 模块类型
/// </summary>
public string ModuleSoure { get; set; }
/// <summary>
/// 数据库提供者

View File

@@ -7,6 +7,6 @@ namespace Yi.Abp.Tool.Application.Contracts
public interface ITemplateGenService: IApplicationService
{
Task<byte[]> CreateModuleAsync(TemplateGenCreateInputDto moduleCreateInputDto);
Task<byte[]> CreateProjectAsync(TemplateGenCreateInputDto moduleCreateInputDto);
Task<List<string>> GetAllTemplatesAsync();
}
}

View File

@@ -16,10 +16,14 @@ using Yi.Framework.Core.Helper;
namespace Yi.Abp.Tool.Application
{
public class TemplateGenService : ApplicationService,ITemplateGenService
public class TemplateGenService : ApplicationService, ITemplateGenService
{
private readonly TemplateGenManager _templateGenManager;
public TemplateGenService(TemplateGenManager templateGenManager) { _templateGenManager = templateGenManager; }
public TemplateGenService(TemplateGenManager templateGenManager)
{
_templateGenManager = templateGenManager;
}
/// <summary>
/// 下载模块文件
@@ -29,8 +33,10 @@ namespace Yi.Abp.Tool.Application
{
moduleCreateInputDto.SetNameReplace();
//模块类型,就是分支小写
var input = moduleCreateInputDto.Adapt<TemplateGenCreateDto>();
input.SetTemplateFilePath(_templateGenManager._toolOptions.ModuleTemplateFilePath);
input.SetTemplateGiteeRef(moduleCreateInputDto.ModuleSoure);
var filePath = await _templateGenManager.CreateTemplateAsync(input);
////考虑从路径中获取
@@ -39,22 +45,15 @@ namespace Yi.Abp.Tool.Application
return await File.ReadAllBytesAsync(filePath);
}
/// <summary>
/// 下载模块文件
/// 获取全部模板列表
/// </summary>
/// <returns></returns>
public async Task<byte[]> CreateProjectAsync(TemplateGenCreateInputDto moduleCreateInputDto)
[HttpGet("template-gen/template")]
public async Task<List<string>> GetAllTemplatesAsync()
{
moduleCreateInputDto.SetNameReplace();
var input = moduleCreateInputDto.Adapt<TemplateGenCreateDto>();
input.SetTemplateFilePath(_templateGenManager._toolOptions.ProjectTemplateFilePath);
var filePath = await _templateGenManager.CreateTemplateAsync(input);
//考虑从路径中获取
// var fileContentType = MimeHelper.GetMimeMapping(Path.GetFileName(filePath));
//设置附件下载,下载名称
return await File.ReadAllBytesAsync(filePath);
return await _templateGenManager.GetAllTemplatesAsync();
}
}
}
}

View File

@@ -9,21 +9,19 @@ namespace Yi.Abp.Tool.Domain.Shared.Dtos
{
public class TemplateGenCreateDto
{
public void SetTemplateFilePath(string templateFilePath)
public void SetTemplateGiteeRef(string moduleType)
{
this.TemplateFilePath = templateFilePath;
this.GiteeRef = moduleType.ToLower();
}
/// <summary>
/// 模板文件路径
/// </summary>
public string TemplateFilePath { get; set; }
/// <summary>
/// 模块名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 模块所属gitee分支
/// </summary>
public string GiteeRef { get; set; }
/// <summary>
/// 数据库提供者

View File

@@ -8,17 +8,6 @@ namespace Yi.Abp.Tool.Domain.Shared.Options
{
public class ToolOptions
{
/// <summary>
/// 模块模板zip文件路径
/// </summary>
public string ModuleTemplateFilePath { get; set; }
/// <summary>
/// 项目模板zip文件路径
/// </summary>
public string ProjectTemplateFilePath { get; set; }
/// <summary>
/// 临时文件目录
/// </summary>

View File

@@ -9,5 +9,8 @@
<ProjectReference Include="..\..\framework\Yi.Framework.Core\Yi.Framework.Core.csproj" />
<ProjectReference Include="..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Options\" />
</ItemGroup>
</Project>

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