Merge branch 'abp' of https://gitee.com/ccnetcore/Yi into abp
@@ -1,4 +1,4 @@
|
||||
<h1 align="center"><img align="left" height="150px" src="https://user-images.githubusercontent.com/68722157/138828506-f58b7c57-5e10-4178-8f7d-5d5e12050113.png"> Yi框架</h1>
|
||||
<h1 align="center"><img align="left" height="150px" src="https://ccnetcore.com/prod-api/wwwroot/logo.png"> Yi框架</h1>
|
||||
<h4 align="center">一套以用户体验出发的.Net8 Web开源框架</h4>
|
||||
<h5 align="center">支持Abp.vNext 版本原生版本、Furion版本,前端后台接入Ruoyi Vue3.0</h5>
|
||||
<h2 align="center">集大成者,终究轮子</h2>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
using System.Diagnostics;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
@@ -75,12 +79,59 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
[scheme] = new string[0]
|
||||
});
|
||||
|
||||
|
||||
options.SchemaFilter<EnumSchemaFilter>();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Swagger文档枚举字段显示枚举属性和枚举值,以及枚举描述
|
||||
/// </summary>
|
||||
public class EnumSchemaFilter : ISchemaFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现接口
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="context"></param>
|
||||
|
||||
public void Apply(OpenApiSchema model, SchemaFilterContext context)
|
||||
{
|
||||
if (context.Type.IsEnum)
|
||||
{
|
||||
model.Enum.Clear();
|
||||
model.Type = "string";
|
||||
model.Format = null;
|
||||
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Enum.GetNames(context.Type)
|
||||
.ToList()
|
||||
.ForEach(name =>
|
||||
{
|
||||
Enum e = (Enum)Enum.Parse(context.Type, name);
|
||||
var descrptionOrNull = GetEnumDescription(e);
|
||||
model.Enum.Add(new OpenApiString(name));
|
||||
stringBuilder.Append($"【枚举:{name}{(descrptionOrNull is null ? string.Empty : $"({descrptionOrNull})")}={Convert.ToInt64(Enum.Parse(context.Type, name))}】<br />");
|
||||
});
|
||||
model.Description= stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetEnumDescription(Enum value)
|
||||
{
|
||||
var fieldInfo = value.GetType().GetField(value.ToString());
|
||||
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
return attributes.Length > 0 ? attributes[0].Description : null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.3" />
|
||||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Validation;
|
||||
|
||||
namespace Yi.Framework.Ddd.Application
|
||||
{
|
||||
@@ -86,7 +89,7 @@ namespace Yi.Framework.Ddd.Application
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[RemoteService(isEnabled: true)]
|
||||
public async Task DeleteAsync(IEnumerable<TKey> id)
|
||||
public virtual async Task DeleteAsync(IEnumerable<TKey> id)
|
||||
{
|
||||
await Repository.DeleteManyAsync(id);
|
||||
}
|
||||
@@ -95,5 +98,34 @@ namespace Yi.Framework.Ddd.Application
|
||||
{
|
||||
return base.DeleteAsync(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public virtual async Task<IActionResult> GetExportExcelAsync(TGetListInput input)
|
||||
{
|
||||
if (input is IPagedResultRequest paged)
|
||||
{
|
||||
paged.SkipCount = 0;
|
||||
paged.MaxResultCount = LimitedResultRequestDto.MaxMaxResultCount;
|
||||
}
|
||||
|
||||
var output = await this.GetListAsync(input);
|
||||
var dirPath = $"/wwwroot/temp";
|
||||
var filePath = $"{dirPath}/{Guid.NewGuid()}.xlsx";
|
||||
if (!Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
MiniExcel.SaveAs(filePath, output.Items);
|
||||
return new FileStreamResult(File.OpenRead(filePath), "application/vnd.ms-excel");
|
||||
}
|
||||
|
||||
public virtual async Task PostImportExcelAsync()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Volo.Abp.Application;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
@@ -8,6 +10,11 @@ namespace Yi.Framework.Ddd.Application
|
||||
typeof(YiFrameworkDddApplicationContractsModule))]
|
||||
public class YiFrameworkDddApplicationModule : AbpModule
|
||||
{
|
||||
|
||||
public override void OnApplicationInitialization(ApplicationInitializationContext context)
|
||||
{
|
||||
//分页限制
|
||||
LimitedResultRequestDto.DefaultMaxResultCount = 10;
|
||||
LimitedResultRequestDto.MaxMaxResultCount = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Linq;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.SqlSugarCore.Repositories
|
||||
{
|
||||
public class SqlSugarObjectRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
|
||||
{
|
||||
public ISqlSugarClient _Db => GetDbContextAsync().Result;
|
||||
private ISugarDbContextProvider<ISqlSugarDbContext> _sugarDbContextProvider;
|
||||
/// <summary>
|
||||
/// 获取DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ISqlSugarClient> GetDbContextAsync()
|
||||
{
|
||||
|
||||
var db = (await _sugarDbContextProvider.GetDbContextAsync()).SqlSugarClient;
|
||||
//await Console.Out.WriteLineAsync("获取的id:" + db.ContextID);
|
||||
return db;
|
||||
}
|
||||
|
||||
public IAsyncQueryableExecuter AsyncExecuter => throw new NotImplementedException();
|
||||
|
||||
public bool? IsChangeTrackingEnabled => throw new NotImplementedException();
|
||||
|
||||
public Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity?> FindAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> GetCountAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> GetQueryableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await (await GetDbContextAsync()).InsertableByObject(entity).ExecuteCommandAsync();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> WithDetails(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<TEntity>> WithDetailsAsync(params Expression<Func<TEntity, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class SqlSugarObjectRepository<TEntity, TKey> : SqlSugarObjectRepository<TEntity>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>
|
||||
{
|
||||
public Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteManyAsync(IEnumerable<TKey> ids, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity?> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,12 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
||||
public SqlSugarTransactionApi(ISqlSugarDbContext sqlsugarDbContext)
|
||||
{
|
||||
_sqlsugarDbContext = sqlsugarDbContext;
|
||||
}
|
||||
|
||||
public ISqlSugarDbContext GetDbContext()
|
||||
{
|
||||
|
||||
return _sqlsugarDbContext;
|
||||
}
|
||||
|
||||
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
||||
|
||||
@@ -82,17 +82,17 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
||||
|
||||
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork)
|
||||
{
|
||||
return unitOfWork.Options.IsTransactional
|
||||
? await CreateDbContextWithTransactionAsync(unitOfWork)
|
||||
: unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
return unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
//return unitOfWork.Options.IsTransactional
|
||||
// ? await CreateDbContextWithTransactionAsync(unitOfWork)
|
||||
// : unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
}
|
||||
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
|
||||
{
|
||||
var transactionApiKey = $"Sqlsugar_Default".ToString();
|
||||
|
||||
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarDatabaseApi;
|
||||
if (activeTransaction == null)
|
||||
{
|
||||
var transactionApiKey = $"Sqlsugar_Default"+Guid.NewGuid().ToString();
|
||||
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarTransactionApi;
|
||||
//if (activeTransaction==null|| activeTransaction.Equals(default(SqlSugarTransactionApi)))
|
||||
//{
|
||||
|
||||
var dbContext = unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
|
||||
var transaction = new SqlSugarTransactionApi(
|
||||
@@ -105,14 +105,15 @@ namespace Yi.Framework.SqlSugarCore.Uow
|
||||
// Console.WriteLine(dbContext.SqlSugarClient.ContextID);
|
||||
await dbContext.SqlSugarClient.Ado.BeginTranAsync();
|
||||
return dbContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// await Console.Out.WriteLineAsync("继续老的事务");
|
||||
// Console.WriteLine(activeTransaction.DbContext.SqlSugarClient);
|
||||
await activeTransaction.DbContext.SqlSugarClient.Ado.BeginTranAsync();
|
||||
return (TDbContext)activeTransaction.DbContext;
|
||||
}
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// var db= activeTransaction.GetDbContext().SqlSugarClient;
|
||||
// // await Console.Out.WriteLineAsync("继续老的事务");
|
||||
// // Console.WriteLine(activeTransaction.DbContext.SqlSugarClient);
|
||||
// await activeTransaction.GetDbContext().SqlSugarClient.Ado.BeginTranAsync();
|
||||
// return (TDbContext)activeTransaction.GetDbContext();
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.AuditLogging;
|
||||
|
||||
namespace Yi.AuditLogging.SqlSugarCore.Entities
|
||||
{
|
||||
public class AuditLogEntity : AuditLog
|
||||
{
|
||||
public AuditLogEntity() { }
|
||||
}
|
||||
}
|
||||
@@ -1,266 +1,348 @@
|
||||
//using System.Linq.Dynamic.Core;
|
||||
//using System.Net;
|
||||
//using Volo.Abp.Auditing;
|
||||
//using Volo.Abp.Domain.Entities;
|
||||
//using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
//using Yi.Framework.SqlSugarCore.Repositories;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Expressions;
|
||||
using System.Net;
|
||||
using Mapster;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Yi.AuditLogging.SqlSugarCore.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Repositories;
|
||||
|
||||
//namespace Volo.Abp.AuditLogging.EntityFrameworkCore;
|
||||
namespace Volo.Abp.AuditLogging.EntityFrameworkCore;
|
||||
|
||||
//public class SqlSugarCoreAuditLogRepository : SqlSugarRepository<AuditLog, Guid>, IAuditLogRepository
|
||||
//{
|
||||
// public SqlSugarCoreAuditLogRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider) : base(sugarDbContextProvider)
|
||||
// {
|
||||
// }
|
||||
public class SqlSugarCoreAuditLogRepository : SqlSugarObjectRepository<AuditLog, Guid>,IAuditLogRepository
|
||||
{
|
||||
public virtual async Task<List<AuditLog>> GetListAsync(
|
||||
string sorting = null,
|
||||
int maxResultCount = 50,
|
||||
int skipCount = 0,
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
string httpMethod = null,
|
||||
string url = null,
|
||||
Guid? userId = null,
|
||||
string userName = null,
|
||||
string applicationName = null,
|
||||
string clientIpAddress = null,
|
||||
string correlationId = null,
|
||||
int? maxExecutionDuration = null,
|
||||
int? minExecutionDuration = null,
|
||||
bool? hasException = null,
|
||||
HttpStatusCode? httpStatusCode = null,
|
||||
bool includeDetails = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = await GetListQueryAsync(
|
||||
startTime,
|
||||
endTime,
|
||||
httpMethod,
|
||||
url,
|
||||
userId,
|
||||
userName,
|
||||
applicationName,
|
||||
clientIpAddress,
|
||||
correlationId,
|
||||
maxExecutionDuration,
|
||||
minExecutionDuration,
|
||||
hasException,
|
||||
httpStatusCode,
|
||||
includeDetails
|
||||
);
|
||||
|
||||
// public virtual async Task<List<AuditLog>> GetListAsync(
|
||||
// string sorting = null,
|
||||
// int maxResultCount = 50,
|
||||
// int skipCount = 0,
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// string httpMethod = null,
|
||||
// string url = null,
|
||||
// Guid? userId = null,
|
||||
// string userName = null,
|
||||
// string applicationName = null,
|
||||
// string clientIpAddress = null,
|
||||
// string correlationId = null,
|
||||
// int? maxExecutionDuration = null,
|
||||
// int? minExecutionDuration = null,
|
||||
// bool? hasException = null,
|
||||
// HttpStatusCode? httpStatusCode = null,
|
||||
// bool includeDetails = false,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var query = await GetListQueryAsync(
|
||||
// startTime,
|
||||
// endTime,
|
||||
// httpMethod,
|
||||
// url,
|
||||
// userId,
|
||||
// userName,
|
||||
// applicationName,
|
||||
// clientIpAddress,
|
||||
// correlationId,
|
||||
// maxExecutionDuration,
|
||||
// minExecutionDuration,
|
||||
// hasException,
|
||||
// httpStatusCode,
|
||||
// includeDetails
|
||||
// );
|
||||
var auditLogs = await query
|
||||
.OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(AuditLog.ExecutionTime) + " DESC") : sorting)
|
||||
.ToPageListAsync(skipCount, maxResultCount, cancellationToken);
|
||||
|
||||
// var auditLogs = await query
|
||||
// .OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(AuditLog.ExecutionTime) + " DESC") : sorting)
|
||||
// .PageBy(skipCount, maxResultCount)
|
||||
// .ToListAsync(GetCancellationToken(cancellationToken));
|
||||
return auditLogs.Adapt<List<AuditLog>>();
|
||||
}
|
||||
|
||||
// return auditLogs;
|
||||
// }
|
||||
public virtual async Task<long> GetCountAsync(
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
string httpMethod = null,
|
||||
string url = null,
|
||||
Guid? userId = null,
|
||||
string userName = null,
|
||||
string applicationName = null,
|
||||
string clientIpAddress = null,
|
||||
string correlationId = null,
|
||||
int? maxExecutionDuration = null,
|
||||
int? minExecutionDuration = null,
|
||||
bool? hasException = null,
|
||||
HttpStatusCode? httpStatusCode = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = await GetListQueryAsync(
|
||||
startTime,
|
||||
endTime,
|
||||
httpMethod,
|
||||
url,
|
||||
userId,
|
||||
userName,
|
||||
applicationName,
|
||||
clientIpAddress,
|
||||
correlationId,
|
||||
maxExecutionDuration,
|
||||
minExecutionDuration,
|
||||
hasException,
|
||||
httpStatusCode
|
||||
);
|
||||
|
||||
// public virtual async Task<long> GetCountAsync(
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// string httpMethod = null,
|
||||
// string url = null,
|
||||
// Guid? userId = null,
|
||||
// string userName = null,
|
||||
// string applicationName = null,
|
||||
// string clientIpAddress = null,
|
||||
// string correlationId = null,
|
||||
// int? maxExecutionDuration = null,
|
||||
// int? minExecutionDuration = null,
|
||||
// bool? hasException = null,
|
||||
// HttpStatusCode? httpStatusCode = null,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var query = await GetListQueryAsync(
|
||||
// startTime,
|
||||
// endTime,
|
||||
// httpMethod,
|
||||
// url,
|
||||
// userId,
|
||||
// userName,
|
||||
// applicationName,
|
||||
// clientIpAddress,
|
||||
// correlationId,
|
||||
// maxExecutionDuration,
|
||||
// minExecutionDuration,
|
||||
// hasException,
|
||||
// httpStatusCode
|
||||
// );
|
||||
var totalCount = await query.CountAsync(cancellationToken);
|
||||
|
||||
// var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken));
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
// return totalCount;
|
||||
// }
|
||||
protected virtual async Task<ISugarQueryable<AuditLogEntity>> GetListQueryAsync(
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
string httpMethod = null,
|
||||
string url = null,
|
||||
Guid? userId = null,
|
||||
string userName = null,
|
||||
string applicationName = null,
|
||||
string clientIpAddress = null,
|
||||
string correlationId = null,
|
||||
int? maxExecutionDuration = null,
|
||||
int? minExecutionDuration = null,
|
||||
bool? hasException = null,
|
||||
HttpStatusCode? httpStatusCode = null,
|
||||
bool includeDetails = false)
|
||||
{
|
||||
var nHttpStatusCode = (int?)httpStatusCode;
|
||||
return (await GetDbContextAsync()).Queryable<AuditLogEntity>()
|
||||
.WhereIF(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
|
||||
.WhereIF(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
|
||||
.WhereIF(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
|
||||
.WhereIF(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "")
|
||||
.WhereIF(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
|
||||
.WhereIF(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
|
||||
.WhereIF(userId != null, auditLog => auditLog.UserId == userId)
|
||||
.WhereIF(userName != null, auditLog => auditLog.UserName == userName)
|
||||
.WhereIF(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
|
||||
.WhereIF(clientIpAddress != null, auditLog => auditLog.ClientIpAddress != null && auditLog.ClientIpAddress == clientIpAddress)
|
||||
.WhereIF(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
|
||||
.WhereIF(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == nHttpStatusCode)
|
||||
.WhereIF(maxExecutionDuration != null && maxExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
|
||||
.WhereIF(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
|
||||
}
|
||||
|
||||
// protected virtual async Task<IQueryable<AuditLog>> GetListQueryAsync(
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// string httpMethod = null,
|
||||
// string url = null,
|
||||
// Guid? userId = null,
|
||||
// string userName = null,
|
||||
// string applicationName = null,
|
||||
// string clientIpAddress = null,
|
||||
// string correlationId = null,
|
||||
// int? maxExecutionDuration = null,
|
||||
// int? minExecutionDuration = null,
|
||||
// bool? hasException = null,
|
||||
// HttpStatusCode? httpStatusCode = null,
|
||||
// bool includeDetails = false)
|
||||
// {
|
||||
// var nHttpStatusCode = (int?)httpStatusCode;
|
||||
// return (await GetDbSetAsync()).AsNoTracking()
|
||||
// .IncludeDetails(includeDetails)
|
||||
// .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
|
||||
// .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
|
||||
// .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
|
||||
// .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "")
|
||||
// .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
|
||||
// .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
|
||||
// .WhereIf(userId != null, auditLog => auditLog.UserId == userId)
|
||||
// .WhereIf(userName != null, auditLog => auditLog.UserName == userName)
|
||||
// .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
|
||||
// .WhereIf(clientIpAddress != null, auditLog => auditLog.ClientIpAddress != null && auditLog.ClientIpAddress == clientIpAddress)
|
||||
// .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
|
||||
// .WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == nHttpStatusCode)
|
||||
// .WhereIf(maxExecutionDuration != null && maxExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
|
||||
// .WhereIf(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
|
||||
// }
|
||||
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
|
||||
DateTime startDate,
|
||||
DateTime endDate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await (await GetDbContextAsync()).Queryable<AuditLogEntity>()
|
||||
.Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)
|
||||
.OrderBy(t => t.ExecutionTime)
|
||||
.GroupBy(t => new { t.ExecutionTime.Date })
|
||||
.Select(g => new { Day =SqlFunc.AggregateMin(g.ExecutionTime), avgExecutionTime = SqlFunc.AggregateAvg( g.ExecutionDuration) })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
// public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
|
||||
// DateTime startDate,
|
||||
// DateTime endDate,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var result = await (await GetDbSetAsync()).AsNoTracking()
|
||||
// .Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)
|
||||
// .OrderBy(t => t.ExecutionTime)
|
||||
// .GroupBy(t => new { t.ExecutionTime.Date })
|
||||
// .Select(g => new { Day = g.Min(t => t.ExecutionTime), avgExecutionTime = g.Average(t => t.ExecutionDuration) })
|
||||
// .ToListAsync(GetCancellationToken(cancellationToken));
|
||||
return result.ToDictionary(element => element.Day.ClearTime(), element => (double)element.avgExecutionTime);
|
||||
}
|
||||
|
||||
// return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime);
|
||||
// }
|
||||
public virtual async Task<EntityChange> GetEntityChange(
|
||||
Guid entityChangeId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entityChange = await (await GetDbContextAsync()).Queryable<EntityChange>()
|
||||
.Where(x => x.Id == entityChangeId)
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstAsync(cancellationToken);
|
||||
|
||||
// [Obsolete("Use WithDetailsAsync method.")]
|
||||
// public override IQueryable<AuditLog> WithDetails()
|
||||
// {
|
||||
// return GetQueryable().IncludeDetails();
|
||||
// }
|
||||
if (entityChange == null)
|
||||
{
|
||||
throw new EntityNotFoundException(typeof(EntityChange));
|
||||
}
|
||||
|
||||
// public override async Task<IQueryable<AuditLog>> WithDetailsAsync()
|
||||
// {
|
||||
// return (await GetQueryableAsync()).IncludeDetails();
|
||||
// }
|
||||
return entityChange;
|
||||
}
|
||||
|
||||
// public virtual async Task<EntityChange> GetEntityChange(
|
||||
// Guid entityChangeId,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var entityChange = await (await GetDbContextAsync()).Set<EntityChange>()
|
||||
// .AsNoTracking()
|
||||
// .IncludeDetails()
|
||||
// .Where(x => x.Id == entityChangeId)
|
||||
// .OrderBy(x => x.Id)
|
||||
// .FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
|
||||
public virtual async Task<List<EntityChange>> GetEntityChangeListAsync(
|
||||
string sorting = null,
|
||||
int maxResultCount = 50,
|
||||
int skipCount = 0,
|
||||
Guid? auditLogId = null,
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
EntityChangeType? changeType = null,
|
||||
string entityId = null,
|
||||
string entityTypeFullName = null,
|
||||
bool includeDetails = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails);
|
||||
|
||||
// if (entityChange == null)
|
||||
// {
|
||||
// throw new EntityNotFoundException(typeof(EntityChange));
|
||||
// }
|
||||
return await query.OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(EntityChange.ChangeTime) + " DESC") : sorting)
|
||||
.ToPageListAsync(skipCount, maxResultCount, cancellationToken);
|
||||
}
|
||||
|
||||
// return entityChange;
|
||||
// }
|
||||
public virtual async Task<long> GetEntityChangeCountAsync(
|
||||
Guid? auditLogId = null,
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
EntityChangeType? changeType = null,
|
||||
string entityId = null,
|
||||
string entityTypeFullName = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName);
|
||||
|
||||
// public virtual async Task<List<EntityChange>> GetEntityChangeListAsync(
|
||||
// string sorting = null,
|
||||
// int maxResultCount = 50,
|
||||
// int skipCount = 0,
|
||||
// Guid? auditLogId = null,
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// EntityChangeType? changeType = null,
|
||||
// string entityId = null,
|
||||
// string entityTypeFullName = null,
|
||||
// bool includeDetails = false,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails);
|
||||
var totalCount = await query.CountAsync(cancellationToken);
|
||||
|
||||
// return await query.OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(EntityChange.ChangeTime) + " DESC") : sorting)
|
||||
// .PageBy(skipCount, maxResultCount)
|
||||
// .ToListAsync(GetCancellationToken(cancellationToken));
|
||||
// }
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
// public virtual async Task<long> GetEntityChangeCountAsync(
|
||||
// Guid? auditLogId = null,
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// EntityChangeType? changeType = null,
|
||||
// string entityId = null,
|
||||
// string entityTypeFullName = null,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName);
|
||||
public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(
|
||||
Guid entityChangeId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var auditLog = await (await GetDbContextAsync()).Queryable<AuditLogEntity>()
|
||||
.Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync(cancellationToken);
|
||||
|
||||
// var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken));
|
||||
return new EntityChangeWithUsername()
|
||||
{
|
||||
EntityChange = auditLog.EntityChanges.First(x => x.Id == entityChangeId),
|
||||
UserName = auditLog.UserName
|
||||
};
|
||||
}
|
||||
|
||||
// return totalCount;
|
||||
// }
|
||||
public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(
|
||||
string entityId,
|
||||
string entityTypeFullName,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var dbContext = await GetDbContextAsync();
|
||||
|
||||
// public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(
|
||||
// Guid entityChangeId,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var auditLog = await (await GetDbSetAsync()).AsNoTracking().IncludeDetails()
|
||||
// .Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync(GetCancellationToken(cancellationToken));
|
||||
var query = dbContext.Queryable<EntityChange>()
|
||||
.Where(x => x.EntityId == entityId && x.EntityTypeFullName == entityTypeFullName);
|
||||
return await query.LeftJoin<AuditLogEntity>((change, audit) => change.AuditLogId == audit.Id)
|
||||
.Select((change, audit) => new EntityChangeWithUsername { EntityChange = change, UserName = audit.UserName }, true)
|
||||
.OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync(cancellationToken);
|
||||
|
||||
// return new EntityChangeWithUsername()
|
||||
// {
|
||||
// EntityChange = auditLog.EntityChanges.First(x => x.Id == entityChangeId),
|
||||
// UserName = auditLog.UserName
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
||||
// public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(
|
||||
// string entityId,
|
||||
// string entityTypeFullName,
|
||||
// CancellationToken cancellationToken = default)
|
||||
// {
|
||||
// var dbContext = await GetDbContextAsync();
|
||||
protected virtual async Task<ISugarQueryable<EntityChange>> GetEntityChangeListQueryAsync(
|
||||
Guid? auditLogId = null,
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
EntityChangeType? changeType = null,
|
||||
string entityId = null,
|
||||
string entityTypeFullName = null,
|
||||
bool includeDetails = false)
|
||||
{
|
||||
return (await GetDbContextAsync())
|
||||
.Queryable<EntityChange>()
|
||||
.WhereIF(auditLogId.HasValue, e => e.AuditLogId == auditLogId)
|
||||
.WhereIF(startTime.HasValue, e => e.ChangeTime >= startTime)
|
||||
.WhereIF(endTime.HasValue, e => e.ChangeTime <= endTime)
|
||||
.WhereIF(changeType.HasValue, e => e.ChangeType == changeType)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(entityTypeFullName), e => e.EntityTypeFullName.Contains(entityTypeFullName));
|
||||
}
|
||||
|
||||
// var query = dbContext.Set<EntityChange>()
|
||||
// .AsNoTracking()
|
||||
// .IncludeDetails()
|
||||
// .Where(x => x.EntityId == entityId && x.EntityTypeFullName == entityTypeFullName);
|
||||
Task<List<AuditLog>> IAuditLogRepository.GetListAsync(string sorting, int maxResultCount, int skipCount, DateTime? startTime, DateTime? endTime, string httpMethod, string url, Guid? userId, string userName, string applicationName, string clientIpAddress, string correlationId, int? maxExecutionDuration, int? minExecutionDuration, bool? hasException, HttpStatusCode? httpStatusCode, bool includeDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// return await (from e in query
|
||||
// join auditLog in dbContext.AuditLogs on e.AuditLogId equals auditLog.Id
|
||||
// select new EntityChangeWithUsername { EntityChange = e, UserName = auditLog.UserName })
|
||||
// .OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync(GetCancellationToken(cancellationToken));
|
||||
// }
|
||||
|
||||
// protected virtual async Task<IQueryable<EntityChange>> GetEntityChangeListQueryAsync(
|
||||
// Guid? auditLogId = null,
|
||||
// DateTime? startTime = null,
|
||||
// DateTime? endTime = null,
|
||||
// EntityChangeType? changeType = null,
|
||||
// string entityId = null,
|
||||
// string entityTypeFullName = null,
|
||||
// bool includeDetails = false)
|
||||
// {
|
||||
// return (await GetDbContextAsync())
|
||||
// .Set<EntityChange>()
|
||||
// .AsNoTracking()
|
||||
// .IncludeDetails(includeDetails)
|
||||
// .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId)
|
||||
// .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime)
|
||||
// .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime)
|
||||
// .WhereIf(changeType.HasValue, e => e.ChangeType == changeType)
|
||||
// .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId)
|
||||
// .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), e => e.EntityTypeFullName.Contains(entityTypeFullName));
|
||||
// }
|
||||
//}
|
||||
|
||||
public Task<AuditLog> GetAsync(Expression<Func<AuditLog, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(Expression<Func<AuditLog, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteDirectAsync(Expression<Func<AuditLog, bool>> predicate, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
IQueryable<AuditLog> IReadOnlyRepository<AuditLog>.WithDetails()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IQueryable<AuditLog> WithDetails(params Expression<Func<AuditLog, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IQueryable<AuditLog>> IReadOnlyRepository<AuditLog>.WithDetailsAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IQueryable<AuditLog>> WithDetailsAsync(params Expression<Func<AuditLog, object>>[] propertySelectors)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IQueryable<AuditLog>> IReadOnlyRepository<AuditLog>.GetQueryableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<AuditLog>> GetListAsync(Expression<Func<AuditLog, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<AuditLog> InsertAsync(AuditLog entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertManyAsync(IEnumerable<AuditLog> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<AuditLog> UpdateAsync(AuditLog entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateManyAsync(IEnumerable<AuditLog> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(AuditLog entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteManyAsync(IEnumerable<AuditLog> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<AuditLog> IReadOnlyBasicRepository<AuditLog, Guid>.GetAsync(Guid id, bool includeDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<AuditLog?> IReadOnlyBasicRepository<AuditLog, Guid>.FindAsync(Guid id, bool includeDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<List<AuditLog>> IReadOnlyBasicRepository<AuditLog>.GetListAsync(bool includeDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<List<AuditLog>> IReadOnlyBasicRepository<AuditLog>.GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.Mapster\Yi.Framework.Mapster.csproj" />
|
||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.AuditLogging;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
@@ -23,11 +18,11 @@ namespace Yi.AuditLogging.SqlSugarCore
|
||||
column.DbTableName = AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogs";
|
||||
|
||||
column.IfTable<AuditLog>()
|
||||
|
||||
|
||||
.UpdateProperty(x => x.Id,
|
||||
x =>
|
||||
{
|
||||
x.IsPrimarykey = true;
|
||||
x.IsPrimarykey = true;
|
||||
})
|
||||
|
||||
.UpdateProperty(x => x.ApplicationName,
|
||||
@@ -38,97 +33,98 @@ namespace Yi.AuditLogging.SqlSugarCore
|
||||
});
|
||||
|
||||
|
||||
//builder.Entity<AuditLog>(b =>
|
||||
//{
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogs", AbpAuditLoggingDbProperties.DbSchema);
|
||||
// builder.Entity<AuditLog>(b =>
|
||||
// {
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogs", AbpAuditLoggingDbProperties.DbSchema);
|
||||
|
||||
// b.ConfigureByConvention();
|
||||
// b.ConfigureByConvention();
|
||||
|
||||
// b.Property(x => x.ApplicationName).HasMaxLength(AuditLogConsts.MaxApplicationNameLength).HasColumnName(nameof(AuditLog.ApplicationName));
|
||||
// b.Property(x => x.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress));
|
||||
// b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName));
|
||||
// b.Property(x => x.ClientId).HasMaxLength(AuditLogConsts.MaxClientIdLength).HasColumnName(nameof(AuditLog.ClientId));
|
||||
// b.Property(x => x.CorrelationId).HasMaxLength(AuditLogConsts.MaxCorrelationIdLength).HasColumnName(nameof(AuditLog.CorrelationId));
|
||||
// b.Property(x => x.BrowserInfo).HasMaxLength(AuditLogConsts.MaxBrowserInfoLength).HasColumnName(nameof(AuditLog.BrowserInfo));
|
||||
// b.Property(x => x.HttpMethod).HasMaxLength(AuditLogConsts.MaxHttpMethodLength).HasColumnName(nameof(AuditLog.HttpMethod));
|
||||
// b.Property(x => x.Url).HasMaxLength(AuditLogConsts.MaxUrlLength).HasColumnName(nameof(AuditLog.Url));
|
||||
// b.Property(x => x.HttpStatusCode).HasColumnName(nameof(AuditLog.HttpStatusCode));
|
||||
// b.Property(x => x.ApplicationName).HasMaxLength(AuditLogConsts.MaxApplicationNameLength).HasColumnName(nameof(AuditLog.ApplicationName));
|
||||
// b.Property(x => x.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress));
|
||||
// b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName));
|
||||
// b.Property(x => x.ClientId).HasMaxLength(AuditLogConsts.MaxClientIdLength).HasColumnName(nameof(AuditLog.ClientId));
|
||||
// b.Property(x => x.CorrelationId).HasMaxLength(AuditLogConsts.MaxCorrelationIdLength).HasColumnName(nameof(AuditLog.CorrelationId));
|
||||
// b.Property(x => x.BrowserInfo).HasMaxLength(AuditLogConsts.MaxBrowserInfoLength).HasColumnName(nameof(AuditLog.BrowserInfo));
|
||||
// b.Property(x => x.HttpMethod).HasMaxLength(AuditLogConsts.MaxHttpMethodLength).HasColumnName(nameof(AuditLog.HttpMethod));
|
||||
// b.Property(x => x.Url).HasMaxLength(AuditLogConsts.MaxUrlLength).HasColumnName(nameof(AuditLog.Url));
|
||||
// b.Property(x => x.HttpStatusCode).HasColumnName(nameof(AuditLog.HttpStatusCode));
|
||||
|
||||
// b.Property(x => x.Comments).HasMaxLength(AuditLogConsts.MaxCommentsLength).HasColumnName(nameof(AuditLog.Comments));
|
||||
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLog.ExecutionDuration));
|
||||
// b.Property(x => x.ImpersonatorTenantId).HasColumnName(nameof(AuditLog.ImpersonatorTenantId));
|
||||
// b.Property(x => x.ImpersonatorUserId).HasColumnName(nameof(AuditLog.ImpersonatorUserId));
|
||||
// b.Property(x => x.ImpersonatorTenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.ImpersonatorTenantName));
|
||||
// b.Property(x => x.ImpersonatorUserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.ImpersonatorUserName));
|
||||
// b.Property(x => x.UserId).HasColumnName(nameof(AuditLog.UserId));
|
||||
// b.Property(x => x.UserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.UserName));
|
||||
// b.Property(x => x.TenantId).HasColumnName(nameof(AuditLog.TenantId));
|
||||
// b.Property(x => x.TenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.TenantName));
|
||||
// b.Property(x => x.Comments).HasMaxLength(AuditLogConsts.MaxCommentsLength).HasColumnName(nameof(AuditLog.Comments));
|
||||
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLog.ExecutionDuration));
|
||||
// b.Property(x => x.ImpersonatorTenantId).HasColumnName(nameof(AuditLog.ImpersonatorTenantId));
|
||||
// b.Property(x => x.ImpersonatorUserId).HasColumnName(nameof(AuditLog.ImpersonatorUserId));
|
||||
// b.Property(x => x.ImpersonatorTenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.ImpersonatorTenantName));
|
||||
// b.Property(x => x.ImpersonatorUserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.ImpersonatorUserName));
|
||||
// b.Property(x => x.UserId).HasColumnName(nameof(AuditLog.UserId));
|
||||
// b.Property(x => x.UserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.UserName));
|
||||
// b.Property(x => x.TenantId).HasColumnName(nameof(AuditLog.TenantId));
|
||||
// b.Property(x => x.TenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.TenantName));
|
||||
|
||||
// b.HasMany(a => a.Actions).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
|
||||
// b.HasMany(a => a.EntityChanges).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
|
||||
// b.HasMany(a => a.Actions).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
|
||||
// b.HasMany(a => a.EntityChanges).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
|
||||
|
||||
// b.HasIndex(x => new { x.TenantId, x.ExecutionTime });
|
||||
// b.HasIndex(x => new { x.TenantId, x.UserId, x.ExecutionTime });
|
||||
// b.HasIndex(x => new { x.TenantId, x.ExecutionTime });
|
||||
// b.HasIndex(x => new { x.TenantId, x.UserId, x.ExecutionTime });
|
||||
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
//});
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
// });
|
||||
|
||||
//builder.Entity<AuditLogAction>(b =>
|
||||
//{
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogActions", AbpAuditLoggingDbProperties.DbSchema);
|
||||
// builder.Entity<AuditLogAction>(b =>
|
||||
// {
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogActions", AbpAuditLoggingDbProperties.DbSchema);
|
||||
|
||||
// b.ConfigureByConvention();
|
||||
// b.ConfigureByConvention();
|
||||
|
||||
// b.Property(x => x.AuditLogId).HasColumnName(nameof(AuditLogAction.AuditLogId));
|
||||
// b.Property(x => x.ServiceName).HasMaxLength(AuditLogActionConsts.MaxServiceNameLength).HasColumnName(nameof(AuditLogAction.ServiceName));
|
||||
// b.Property(x => x.MethodName).HasMaxLength(AuditLogActionConsts.MaxMethodNameLength).HasColumnName(nameof(AuditLogAction.MethodName));
|
||||
// b.Property(x => x.Parameters).HasMaxLength(AuditLogActionConsts.MaxParametersLength).HasColumnName(nameof(AuditLogAction.Parameters));
|
||||
// b.Property(x => x.ExecutionTime).HasColumnName(nameof(AuditLogAction.ExecutionTime));
|
||||
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLogAction.ExecutionDuration));
|
||||
// b.Property(x => x.AuditLogId).HasColumnName(nameof(AuditLogAction.AuditLogId));
|
||||
// b.Property(x => x.ServiceName).HasMaxLength(AuditLogActionConsts.MaxServiceNameLength).HasColumnName(nameof(AuditLogAction.ServiceName));
|
||||
// b.Property(x => x.MethodName).HasMaxLength(AuditLogActionConsts.MaxMethodNameLength).HasColumnName(nameof(AuditLogAction.MethodName));
|
||||
// b.Property(x => x.Parameters).HasMaxLength(AuditLogActionConsts.MaxParametersLength).HasColumnName(nameof(AuditLogAction.Parameters));
|
||||
// b.Property(x => x.ExecutionTime).HasColumnName(nameof(AuditLogAction.ExecutionTime));
|
||||
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLogAction.ExecutionDuration));
|
||||
|
||||
// b.HasIndex(x => new { x.AuditLogId });
|
||||
// b.HasIndex(x => new { x.TenantId, x.ServiceName, x.MethodName, x.ExecutionTime });
|
||||
// b.HasIndex(x => new { x.AuditLogId });
|
||||
// b.HasIndex(x => new { x.TenantId, x.ServiceName, x.MethodName, x.ExecutionTime });
|
||||
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
//});
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
// });
|
||||
|
||||
//builder.Entity<EntityChange>(b =>
|
||||
//{
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityChanges", AbpAuditLoggingDbProperties.DbSchema);
|
||||
// builder.Entity<EntityChange>(b =>
|
||||
// {
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityChanges", AbpAuditLoggingDbProperties.DbSchema);
|
||||
|
||||
// b.ConfigureByConvention();
|
||||
// b.ConfigureByConvention();
|
||||
|
||||
// b.Property(x => x.EntityTypeFullName).HasMaxLength(EntityChangeConsts.MaxEntityTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityChange.EntityTypeFullName));
|
||||
// b.Property(x => x.EntityId).HasMaxLength(EntityChangeConsts.MaxEntityIdLength).IsRequired().HasColumnName(nameof(EntityChange.EntityId));
|
||||
// b.Property(x => x.AuditLogId).IsRequired().HasColumnName(nameof(EntityChange.AuditLogId));
|
||||
// b.Property(x => x.ChangeTime).IsRequired().HasColumnName(nameof(EntityChange.ChangeTime));
|
||||
// b.Property(x => x.ChangeType).IsRequired().HasColumnName(nameof(EntityChange.ChangeType));
|
||||
// b.Property(x => x.TenantId).HasColumnName(nameof(EntityChange.TenantId));
|
||||
// b.Property(x => x.EntityTypeFullName).HasMaxLength(EntityChangeConsts.MaxEntityTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityChange.EntityTypeFullName));
|
||||
// b.Property(x => x.EntityId).HasMaxLength(EntityChangeConsts.MaxEntityIdLength).IsRequired().HasColumnName(nameof(EntityChange.EntityId));
|
||||
// b.Property(x => x.AuditLogId).IsRequired().HasColumnName(nameof(EntityChange.AuditLogId));
|
||||
// b.Property(x => x.ChangeTime).IsRequired().HasColumnName(nameof(EntityChange.ChangeTime));
|
||||
// b.Property(x => x.ChangeType).IsRequired().HasColumnName(nameof(EntityChange.ChangeType));
|
||||
// b.Property(x => x.TenantId).HasColumnName(nameof(EntityChange.TenantId));
|
||||
|
||||
// b.HasMany(a => a.PropertyChanges).WithOne().HasForeignKey(x => x.EntityChangeId);
|
||||
// b.HasMany(a => a.PropertyChanges).WithOne().HasForeignKey(x => x.EntityChangeId);
|
||||
|
||||
// b.HasIndex(x => new { x.AuditLogId });
|
||||
// b.HasIndex(x => new { x.TenantId, x.EntityTypeFullName, x.EntityId });
|
||||
// b.HasIndex(x => new { x.AuditLogId });
|
||||
// b.HasIndex(x => new { x.TenantId, x.EntityTypeFullName, x.EntityId });
|
||||
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
//});
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
// });
|
||||
|
||||
//builder.Entity<EntityPropertyChange>(b =>
|
||||
//{
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityPropertyChanges", AbpAuditLoggingDbProperties.DbSchema);
|
||||
// builder.Entity<EntityPropertyChange>(b =>
|
||||
// {
|
||||
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityPropertyChanges", AbpAuditLoggingDbProperties.DbSchema);
|
||||
|
||||
// b.ConfigureByConvention();
|
||||
// b.ConfigureByConvention();
|
||||
|
||||
// b.Property(x => x.NewValue).HasMaxLength(EntityPropertyChangeConsts.MaxNewValueLength).HasColumnName(nameof(EntityPropertyChange.NewValue));
|
||||
// b.Property(x => x.PropertyName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName));
|
||||
// b.Property(x => x.PropertyTypeFullName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyTypeFullName));
|
||||
// b.Property(x => x.OriginalValue).HasMaxLength(EntityPropertyChangeConsts.MaxOriginalValueLength).HasColumnName(nameof(EntityPropertyChange.OriginalValue));
|
||||
// b.Property(x => x.NewValue).HasMaxLength(EntityPropertyChangeConsts.MaxNewValueLength).HasColumnName(nameof(EntityPropertyChange.NewValue));
|
||||
// b.Property(x => x.PropertyName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName));
|
||||
// b.Property(x => x.PropertyTypeFullName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyTypeFullName));
|
||||
// b.Property(x => x.OriginalValue).HasMaxLength(EntityPropertyChangeConsts.MaxOriginalValueLength).HasColumnName(nameof(EntityPropertyChange.OriginalValue));
|
||||
|
||||
// b.HasIndex(x => new { x.EntityChangeId });
|
||||
// b.HasIndex(x => new { x.EntityChangeId });
|
||||
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
//});
|
||||
// b.ApplyObjectExtensionMappings();
|
||||
// });
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using Volo.Abp.AuditLogging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Volo.Abp.AuditLogging;
|
||||
using Volo.Abp.AuditLogging.EntityFrameworkCore;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.SqlSugarCore;
|
||||
|
||||
@@ -6,11 +9,13 @@ namespace Yi.AuditLogging.SqlSugarCore
|
||||
{
|
||||
[DependsOn(typeof(AbpAuditLoggingDomainModule))]
|
||||
[DependsOn(typeof(YiFrameworkSqlSugarCoreModule))]
|
||||
public class YiAuditLoggingSqlSugarCoreModule:AbpModule
|
||||
public class YiAuditLoggingSqlSugarCoreModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
context.Services.Replace(new ServiceDescriptor(typeof(IAuditLogRepository), typeof(SqlSugarCoreAuditLogRepository), lifetime: ServiceLifetime.Transient));
|
||||
context.Services.AddYiDbContext<YiAuditLoggingDbContext>();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Article
|
||||
{
|
||||
public class ArticleImprotDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 主题id
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Guid DiscussId { get; set; }
|
||||
|
||||
public Guid ArticleParentId { get; set; }= Guid.Empty;
|
||||
|
||||
public ArticleImportTypeEnum ImportType { get; set; } = ArticleImportTypeEnum.Defalut;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -13,8 +15,10 @@ using Yi.Framework.Bbs.Application.Contracts.Dtos.Plate;
|
||||
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Extensions;
|
||||
using Yi.Framework.Bbs.Domain.Managers;
|
||||
using Yi.Framework.Bbs.Domain.Repositories;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Model;
|
||||
using Yi.Framework.Core.Extensions;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Domain.Authorization;
|
||||
@@ -32,18 +36,20 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
{
|
||||
public ArticleService(IArticleRepository articleRepository,
|
||||
ISqlSugarRepository<DiscussEntity> discussRepository,
|
||||
IDiscussService discussService) : base(articleRepository)
|
||||
IDiscussService discussService,
|
||||
ForumManager forumManager) : base(articleRepository)
|
||||
{
|
||||
|
||||
_articleRepository = articleRepository;
|
||||
_discussRepository = discussRepository;
|
||||
_discussService = discussService;
|
||||
|
||||
_forumManager = forumManager;
|
||||
|
||||
}
|
||||
private IArticleRepository _articleRepository { get; set; }
|
||||
private ISqlSugarRepository<DiscussEntity> _discussRepository { get; set; }
|
||||
private IDiscussService _discussService { get; set; }
|
||||
private ForumManager _forumManager;
|
||||
private IArticleRepository _articleRepository;
|
||||
private ISqlSugarRepository<DiscussEntity> _discussRepository;
|
||||
private IDiscussService _discussService;
|
||||
|
||||
public override async Task<PagedResultDto<ArticleGetListOutputDto>> GetListAsync(ArticleGetListInputVo input)
|
||||
{
|
||||
@@ -134,6 +140,41 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 导入文章
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task PostImportAsync([FromQuery] ArticleImprotDto input, [FromForm][Required] IFormFileCollection file)
|
||||
{
|
||||
var fileObjs = new List<FileObject>();
|
||||
if (file.Count > 0)
|
||||
{
|
||||
foreach (var item in file)
|
||||
{
|
||||
if (item.Length > 0)
|
||||
{
|
||||
using (var stream = item.OpenReadStream())
|
||||
{
|
||||
using (var fileStream = new MemoryStream())
|
||||
{
|
||||
await item.CopyToAsync(fileStream);
|
||||
var bytes = fileStream.ToArray();
|
||||
|
||||
// 将字节转换成字符串
|
||||
var content = Encoding.UTF8.GetString(bytes);
|
||||
fileObjs.Add(new FileObject() { FileName = item.FileName, Content = content });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UserFriendlyException("未选择文件");
|
||||
}
|
||||
//使用简单工厂根据传入的类型进行判断
|
||||
await _forumManager.PostImportAsync(input.DiscussId, input.ArticleParentId, fileObjs, input.ImportType);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,5 +18,16 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
{
|
||||
return Task.FromResult("你好世界");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取头像文件
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<string> GetIcon()
|
||||
{
|
||||
|
||||
return Directory.GetFiles("wwwroot/icon").Select(x => "wwwroot/icon/"+ Path.GetFileName(x)).ToList();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Enums
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum ArticleImportTypeEnum
|
||||
{
|
||||
[Description("默认导入方式")]
|
||||
Defalut,
|
||||
|
||||
[Description("vuePresss方式")]
|
||||
VuePress
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Shared.Model
|
||||
{
|
||||
public class FileObject
|
||||
{
|
||||
public string Content { get; set; }
|
||||
public string FileName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Model;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.ArticleImport
|
||||
{
|
||||
public abstract class AbstractArticleImport
|
||||
{
|
||||
public virtual List<ArticleEntity> Import(Guid discussId,Guid articleParentId, List<FileObject> fileObjs)
|
||||
{
|
||||
var articles = Convert(fileObjs);
|
||||
articles.ForEach(article =>
|
||||
{
|
||||
article.DiscussId = discussId;
|
||||
article.ParentId = articleParentId;
|
||||
});
|
||||
return articles;
|
||||
}
|
||||
public abstract List<ArticleEntity> Convert(List<FileObject> fileObjs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Model;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.ArticleImport
|
||||
{
|
||||
internal class DefaultArticleImport : AbstractArticleImport
|
||||
{
|
||||
public override List<ArticleEntity> Convert(List<FileObject> fileObjs)
|
||||
{
|
||||
return fileObjs.OrderBy(x => x.FileName).Select(x => new ArticleEntity { Name = x.FileName, Content = x.Content }).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Model;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers.ArticleImport
|
||||
{
|
||||
internal class VuePressArticleImport : AbstractArticleImport
|
||||
{
|
||||
public override List<ArticleEntity> Convert(List<FileObject> fileObjs)
|
||||
{
|
||||
//排序及处理目录名称
|
||||
var fileNameHandler = fileObjs.OrderBy(x => x.FileName).Select(x =>
|
||||
{
|
||||
var f = new FileObject { Content = x.Content };
|
||||
|
||||
//除去数字
|
||||
f.FileName = x.FileName.Split('.')[1];
|
||||
return f;
|
||||
});
|
||||
|
||||
|
||||
//处理内容
|
||||
var fileContentHandler= fileNameHandler.Select(x =>
|
||||
{
|
||||
var f = new FileObject { FileName = x.FileName };
|
||||
var lines = x.Content.SplitToLines();
|
||||
|
||||
var num = 0;
|
||||
var startIndex = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
if (lines[i] == "---")
|
||||
{
|
||||
num++;
|
||||
if (num == 2)
|
||||
{
|
||||
startIndex = i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
var linesRef = lines.ToList();
|
||||
|
||||
linesRef.RemoveRange(0, startIndex+1);
|
||||
var result = string.Join(Environment.NewLine, linesRef);
|
||||
f.Content = result;
|
||||
return f;
|
||||
});
|
||||
|
||||
var output = fileContentHandler.Select(x => new ArticleEntity() { Content = x.Content, Name = x.FileName }).ToList();
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Managers.ArticleImport;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Model;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Managers
|
||||
@@ -9,14 +14,16 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
/// </summary>
|
||||
public class ForumManager : DomainService
|
||||
{
|
||||
public readonly ISqlSugarRepository<DiscussEntity,Guid> _discussRepository;
|
||||
public readonly ISqlSugarRepository<DiscussEntity, Guid> _discussRepository;
|
||||
public readonly ISqlSugarRepository<PlateEntity, Guid> _plateEntityRepository;
|
||||
public readonly ISqlSugarRepository<CommentEntity, Guid> _commentRepository;
|
||||
public ForumManager(ISqlSugarRepository<DiscussEntity, Guid> discussRepository, ISqlSugarRepository<PlateEntity, Guid> plateEntityRepository, ISqlSugarRepository<CommentEntity, Guid> commentRepository)
|
||||
public readonly ISqlSugarRepository<ArticleEntity, Guid> _articleRepository;
|
||||
public ForumManager(ISqlSugarRepository<DiscussEntity, Guid> discussRepository, ISqlSugarRepository<PlateEntity, Guid> plateEntityRepository, ISqlSugarRepository<CommentEntity, Guid> commentRepository, ISqlSugarRepository<ArticleEntity, Guid> articleRepository)
|
||||
{
|
||||
_discussRepository = discussRepository;
|
||||
_plateEntityRepository = plateEntityRepository;
|
||||
_commentRepository = commentRepository;
|
||||
_articleRepository = articleRepository;
|
||||
}
|
||||
|
||||
//主题是不能直接创建的,需要由领域服务统一创建
|
||||
@@ -36,5 +43,35 @@ namespace Yi.Framework.Bbs.Domain.Managers
|
||||
entity.RootId = rootId;
|
||||
return await _commentRepository.InsertReturnEntityAsync(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入文章
|
||||
/// </summary>
|
||||
/// <param name="discussId"></param>
|
||||
/// <param name="articleParentId"></param>
|
||||
/// <param name="fileObjs"></param>
|
||||
/// <param name="importType"></param>
|
||||
/// <returns></returns>
|
||||
public async Task PostImportAsync(Guid discussId,Guid articleParentId, List<FileObject> fileObjs, ArticleImportTypeEnum importType)
|
||||
{
|
||||
AbstractArticleImport abstractArticleImport = default;
|
||||
switch (importType)
|
||||
{
|
||||
case ArticleImportTypeEnum.Defalut:
|
||||
abstractArticleImport = new DefaultArticleImport();
|
||||
|
||||
break;
|
||||
case ArticleImportTypeEnum.VuePress:
|
||||
abstractArticleImport = new VuePressArticleImport();
|
||||
break;
|
||||
|
||||
default: abstractArticleImport = new DefaultArticleImport(); break;
|
||||
}
|
||||
|
||||
var articleHandled = abstractArticleImport.Import(discussId, articleParentId, fileObjs);
|
||||
|
||||
//await _articleRepository.InsertManyAsync(articleHandled);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,6 +248,17 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
throw new UserFriendlyException("验证码错误");
|
||||
}
|
||||
|
||||
private void ValidateUserName(RegisterDto input)
|
||||
{
|
||||
// 正则表达式,匹配只包含数字和字母的字符串
|
||||
string pattern = @"^[a-zA-Z0-9]+$";
|
||||
|
||||
bool isMatch = Regex.IsMatch(input.UserName, pattern);
|
||||
if (!isMatch)
|
||||
{
|
||||
throw new UserFriendlyException("用户名不能包含除【字母】与【数字】的其他字符");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册,需要验证码通过
|
||||
@@ -276,6 +287,10 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
{
|
||||
throw new UserFriendlyException("密码需大于等于6位!");
|
||||
}
|
||||
|
||||
//效验用户名
|
||||
ValidateUserName(input);
|
||||
|
||||
//效验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
await ValidationPhoneCaptchaAsync(input);
|
||||
|
||||
@@ -283,7 +298,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
|
||||
//输入的用户名与电话号码都不能在数据库中存在
|
||||
UserEntity user = new();
|
||||
var isExist = await _userRepository.IsAnyAsync(x =>x.UserName == input.UserName|| x.Phone == input.Phone);
|
||||
var isExist = await _userRepository.IsAnyAsync(x => x.UserName == input.UserName || x.Phone == input.Phone);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException("用户已存在,注册失败");
|
||||
|
||||
@@ -21,13 +21,11 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
public class FileService : ApplicationService, IFileService
|
||||
{
|
||||
private readonly IRepository<FileAggregateRoot> _repository;
|
||||
private readonly HttpContext _httpContext;
|
||||
private IGuidGenerator _guidGenerator;
|
||||
public FileService(IRepository<FileAggregateRoot> repository, IHttpContextAccessor httpContextAccessor, IGuidGenerator guidGenerator)
|
||||
public FileService(IRepository<FileAggregateRoot> repository, IGuidGenerator guidGenerator)
|
||||
{
|
||||
_guidGenerator = guidGenerator;
|
||||
_repository = repository;
|
||||
_httpContext = httpContextAccessor.HttpContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Yi.Abp.SqlSugarCore
|
||||
base.CustomDataFilter();
|
||||
}
|
||||
|
||||
|
||||
protected override void DataExecuted(object oldValue, DataAfterModel entityInfo)
|
||||
{
|
||||
base.DataExecuted(oldValue, entityInfo);
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\icon\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -37,7 +40,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="logs\" />
|
||||
<Folder Include="wwwroot\" />
|
||||
<Folder Include="wwwroot\icon\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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;
|
||||
@@ -64,6 +66,7 @@ namespace Yi.Abp.Web
|
||||
service.AddControllers().AddNewtonsoftJson(options =>
|
||||
{
|
||||
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||
options.SerializerSettings.Converters.Add(new StringEnumConverter());
|
||||
});
|
||||
|
||||
Configure<AbpAntiForgeryOptions>(options =>
|
||||
@@ -150,6 +153,11 @@ namespace Yi.Abp.Web
|
||||
|
||||
//swagger
|
||||
app.UseYiSwagger();
|
||||
|
||||
//静态资源
|
||||
app.UseStaticFiles("/api/app/wwwroot");
|
||||
app.UseDefaultFiles();
|
||||
app.UseDirectoryBrowser("/api/app/wwwroot");
|
||||
|
||||
//工作单元
|
||||
app.UseUnitOfWork();
|
||||
|
||||
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/0.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/1.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/2.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/3.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/4.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/5.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/6.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/8.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/icon/9.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
Yi.Abp.Net8/src/Yi.Abp.Web/wwwroot/logo.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
@@ -6,7 +6,7 @@ import { Session } from "@/utils/storage";
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
|
||||
const { VITE_APP_ENV_NAME } = import.meta.env;
|
||||
const { getToken } = useAuths();
|
||||
const { getToken, removeToken } = useAuths();
|
||||
|
||||
const { base_url, request_timeout, pre_interface } = config;
|
||||
export const PATH_URL = base_url[VITE_APP_ENV_NAME];
|
||||
@@ -69,6 +69,7 @@ service.interceptors.response.use(
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}).then(() => {
|
||||
removeToken();
|
||||
router.push("/login");
|
||||
});
|
||||
return;
|
||||
|
||||
BIN
readme/1.png
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 108 KiB |
BIN
readme/2.png
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 131 KiB |
BIN
readme/3.png
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 88 KiB |
BIN
readme/4.png
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 151 KiB |
BIN
readme/5.png
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 112 KiB |
BIN
readme/6.png
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 94 KiB |
BIN
readme/7.png
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 141 KiB |
BIN
readme/8.png
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 107 KiB |
BIN
readme/9.png
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 116 KiB |