diff --git a/WorkFlowCore/Commons/Common.AppService/Dtos/BaseCreationDto.cs b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseCreationDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..7c13865d41021ab146ec5295d36c811d7cf1d4fc --- /dev/null +++ b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseCreationDto.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.AppService.Dtos +{ + public class BaseCreationDto : BaseCreationDto + { + + } + public class BaseCreationDto : BaseDto + { + /// + /// 创建用户 + /// + public string CreatedUserId { get; set; } + /// + /// 创建时间 + /// + public DateTime CreationTime { get; set; } + } +} diff --git a/WorkFlowCore/Commons/Common.AppService/Dtos/BaseDto.cs b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..64052527d3eb0eb96cd4917c548d54be1e38db87 --- /dev/null +++ b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.AppService.Dtos +{ + public class BaseDto : BaseDto + { + + } + public class BaseDto + { + public TKey Id { get; set; } + } +} diff --git a/WorkFlowCore/Commons/Common.AppService/Dtos/BaseModificationDto.cs b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseModificationDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..ee2a09cb40eb1ffd10e4ccad748d5a699af03651 --- /dev/null +++ b/WorkFlowCore/Commons/Common.AppService/Dtos/BaseModificationDto.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.AppService.Dtos +{ + public class BaseModificationDto: BaseModificationDto + { + + } + public class BaseModificationDto: BaseCreationDto + { + /// + /// 更新时间 + /// + public DateTime ModifiedTime { get; set; } + /// + /// 更新用户 + /// + public string ModifiedUserId { get; set; } + } +} diff --git a/WorkFlowCore/Commons/Common.BackgroundWorker/BackgroundWorkerModule.cs b/WorkFlowCore/Commons/Common.BackgroundWorker/BackgroundWorkerModule.cs index 8359895d0ba935664e8776cdfa9c2de72d59993b..15b14148806d27ad3602ab9bc8b6d1ca9b935acc 100644 --- a/WorkFlowCore/Commons/Common.BackgroundWorker/BackgroundWorkerModule.cs +++ b/WorkFlowCore/Commons/Common.BackgroundWorker/BackgroundWorkerModule.cs @@ -22,8 +22,6 @@ namespace Common.BackgroundWorker { services.AddSingleton(provider => new QuartzWorkerConfig { Assemblies = assemblies,RedisConnectionString = redisConnectionString}); - - var types = QuartzWorkerManager.InitWorkers(assemblies); foreach (var type in types) services.AddScoped(type); @@ -31,7 +29,6 @@ namespace Common.BackgroundWorker services.AddScoped(); services.AddScoped(); - services.AddScoped(); return services; } diff --git a/WorkFlowCore/Commons/Common.BackgroundWorker/Common.BackgroundWorker.csproj b/WorkFlowCore/Commons/Common.BackgroundWorker/Common.BackgroundWorker.csproj index 0a3b92c384b8ca360b3606d12d78656370669470..4f4a69a1d4b8caabc4602b1b41158e024ff8cce9 100644 --- a/WorkFlowCore/Commons/Common.BackgroundWorker/Common.BackgroundWorker.csproj +++ b/WorkFlowCore/Commons/Common.BackgroundWorker/Common.BackgroundWorker.csproj @@ -15,6 +15,7 @@ + diff --git a/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/CustomerJob.cs b/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/CustomerJob.cs index 3951e427e236349fd7bdd6faadeaa0a843ed85f1..f467def601e2208a25a292bc0234c2e6e41149fb 100644 --- a/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/CustomerJob.cs +++ b/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/CustomerJob.cs @@ -1,4 +1,5 @@ -using Common.EventBus; +using Common.DistributedLock; +using Common.EventBus; using Common.IBaseRepositories; using Common.QuartzImplement.BackgroundWorker; using Common.UnitOfWork; @@ -17,7 +18,6 @@ namespace Common.BackgroundWorker.QuartzImplement /// public class CustomerJob:IJob { - private readonly DistributiveLock redisClient; private readonly IJob job; private readonly IUnitOfWork unitOfWork; private readonly IEventBus eventBus; @@ -27,7 +27,6 @@ namespace Common.BackgroundWorker.QuartzImplement { this.serviceProvider = serviceProvider; this.job = job; - this.redisClient = serviceProvider.GetService(); this.unitOfWork = serviceProvider.GetService(); this.eventBus = serviceProvider.GetService(); } @@ -35,19 +34,24 @@ namespace Common.BackgroundWorker.QuartzImplement public async Task Execute(IJobExecutionContext context) { //TODO 加一个分布式锁,如果有同样的任务运行就不再执行,缓存时间暂时设为 1 天 + + var key = job.GetType().FullName; - if (!redisClient.Lock(key, TimeSpan.FromDays(1))) - return; - try - { - await job.Execute(context); - if (unitOfWork==null||unitOfWork.Commit()) eventBus?.Trigger(); - } - catch (Exception ex) + var distributedLock = DistributedLockManager.NewLock(key); + distributedLock.CanLock(async () => { - Console.WriteLine($"{job.GetType().FullName} 作业异常:{ex.ToString()}"); - } - redisClient.Unlock(key); + try + { + await job.Execute(context); + if (unitOfWork == null || unitOfWork.Commit()) eventBus?.Trigger(); + } + catch (Exception ex) + { + Console.WriteLine($"{job.GetType().FullName} 作业异常:{ex.ToString()}"); + } + + }, TimeSpan.FromDays(1)); + } } } diff --git a/WorkFlowCore/Commons/Common.BaseRepositories4EF/EfContextExtensions.cs b/WorkFlowCore/Commons/Common.BaseRepositories4EF/EfContextExtensions.cs index 4af10838e5fff3cc75c5e894db1cdd8a203d8897..e1476814ddb0e335acbf0f226a4feb8b3c3f556a 100644 --- a/WorkFlowCore/Commons/Common.BaseRepositories4EF/EfContextExtensions.cs +++ b/WorkFlowCore/Commons/Common.BaseRepositories4EF/EfContextExtensions.cs @@ -21,5 +21,17 @@ namespace Common.BaseRepositories4EF } return queryable; } + + public static IQueryable AddSoftDeleteContition(this IQueryable queryable, ICommonSession session) where TEntity : class, IEntity + { + if (typeof(ISoftDeleteEntity).IsAssignableFrom(typeof(TEntity))) + { + if (!string.IsNullOrEmpty(session?.User?.TenantId)) + { + queryable = queryable.Where("Deleted={0}", true); + } + } + return queryable; + } } } diff --git a/WorkFlowCore/Commons/Common.Caching.Redis/Common.Caching.Redis.csproj b/WorkFlowCore/Commons/Common.Caching.Redis/Common.Caching.Redis.csproj new file mode 100644 index 0000000000000000000000000000000000000000..af9b74885e3e869b6762c7bea5c2b5dc508e8ee6 --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching.Redis/Common.Caching.Redis.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/WorkFlowCore/Commons/Common.Caching.Redis/CommonCache.cs b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCache.cs new file mode 100644 index 0000000000000000000000000000000000000000..5a76ba2d0434b2bc217dc020aa6fcaee3d8f7150 --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCache.cs @@ -0,0 +1,102 @@ +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.StackExchangeRedis; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Common.Caching.Redis +{ + public class CommonCache : RedisCache, ICommonCache + { + public CommonCache(IOptions optionsAccessor) : base(optionsAccessor) + { + } + + public TValue Get(string key) + { + var value = base.Get(key); + return ToTValue(value); + } + + public async Task GetAsync(string key, CancellationToken token = default) + { + var value = await base.GetAsync(key, token); + return ToTValue(value); + } + + public TValue GetOrSet(string key, Func value, DistributedCacheEntryOptions options) + { + var _value = Get(key); + if (_value == null) + { + if(value !=null) + { + _value = value.Invoke(); + Set(key, _value, options); + } + + } + return _value; + + } + + public TValue GetOrSet(string key, Func value, TimeSpan? absoluteExpirationRelativeToNow) + { + return GetOrSet(key, value, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow }); + } + + public void Set(string key, TValue value, DistributedCacheEntryOptions options) + { + try + { + var _value = ToBinaryValue(value); + base.Set(key, _value, options); + } + catch (Exception ex) + { + // + } + } + + public void Set(string key, TValue value, TimeSpan? absoluteExpirationRelativeToNow) + { + Set(key, value, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow }); + } + + public Task SetAsync(string key, TValue value, DistributedCacheEntryOptions options, CancellationToken token = default) + { + try + { + var _value = ToBinaryValue(value); + return base.SetAsync(key, _value, options, token); + } + catch (Exception ex) + { + return Task.CompletedTask; + } + } + + public Task SetAsync(string key, TValue value, TimeSpan? absoluteExpirationRelativeToNow, CancellationToken token = default) + { + return SetAsync(key, value, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow }, token); + } + + protected virtual byte[] ToBinaryValue(TValue value) + { + if (value == null) return null; + return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)); + + } + + protected virtual TValue ToTValue(byte[] value) + { + if (value == null) return default; + return JsonConvert.DeserializeObject(Encoding.UTF8.GetString(value)); + + } + } +} diff --git a/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisConfigure.cs b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisConfigure.cs new file mode 100644 index 0000000000000000000000000000000000000000..47625e4605158fa372f298b5c74bd02f005f627d --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisConfigure.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.Caching.Redis +{ + public class CommonCachingRedisConfigure + { + /// + /// redis 链接字符串 + /// 为了实现分布式场景下定时任务不同时运行 + /// + public string RedisConnectionString { get; set; } + } +} diff --git a/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisModule.cs b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..79b845223d67f0ba6c768b38494beba7cd70791e --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching.Redis/CommonCachingRedisModule.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.Caching.Redis +{ + public static class CommonCachingRedisModule + { + + public static IServiceCollection AddCommonCachingRedis(this IServiceCollection services,Action options) + { + var config = new CommonCachingRedisConfigure(); + options?.Invoke(config); + + services.AddStackExchangeRedisCache(options => + { + var redisConfiguration = config.RedisConnectionString; + if (!string.IsNullOrEmpty(redisConfiguration)) + { + options.Configuration = redisConfiguration; + } + }); + + services.Replace(ServiceDescriptor.Singleton()); + + return services; + } + + + + + + } +} diff --git a/WorkFlowCore/Commons/Common.Caching/Common.Caching.csproj b/WorkFlowCore/Commons/Common.Caching/Common.Caching.csproj index 8b960c939b35f3cd2a8a63c00d1e1168467f32fd..9ec76102360f3753aac2065bae97bfd5e9e7f8b1 100644 --- a/WorkFlowCore/Commons/Common.Caching/Common.Caching.csproj +++ b/WorkFlowCore/Commons/Common.Caching/Common.Caching.csproj @@ -9,4 +9,8 @@ + + + + diff --git a/WorkFlowCore/Commons/Common.Caching/CommonCacheManager.cs b/WorkFlowCore/Commons/Common.Caching/CommonCacheManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..0181eba601303863071382c56adb30bd5143d24d --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching/CommonCacheManager.cs @@ -0,0 +1,14 @@ +using Common.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.Caching +{ + public class CommonCacheManager + { + + public static ICommonCache Current { get => GlobalServiceProvider.Current.GetService(); } + } +} diff --git a/WorkFlowCore/Commons/Common.Caching/CommonCachingModule.cs b/WorkFlowCore/Commons/Common.Caching/CommonCachingModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..869991409ebbcd8186347d348838fa5a2cb5898d --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching/CommonCachingModule.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.Caching +{ + public static class CommonCachingModule + { + + } +} diff --git a/WorkFlowCore/Commons/Common.Caching/ICommonCache.cs b/WorkFlowCore/Commons/Common.Caching/ICommonCache.cs new file mode 100644 index 0000000000000000000000000000000000000000..96bc45b5bd0ad90a4e65d8a35323c28d8f8b4f96 --- /dev/null +++ b/WorkFlowCore/Commons/Common.Caching/ICommonCache.cs @@ -0,0 +1,22 @@ +using System; +using JetBrains.Annotations; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.Extensions.Caching.Distributed; + +namespace Common.Caching +{ + public interface ICommonCache : IDistributedCache + { + TValue Get(string key); + Task GetAsync(string key, CancellationToken token = default); + void Set(string key, TValue value, DistributedCacheEntryOptions options); + TValue GetOrSet(string key, Func value, DistributedCacheEntryOptions options); + void Set(string key, TValue value, TimeSpan? absoluteExpirationRelativeToNow); + TValue GetOrSet(string key, Func value, TimeSpan? absoluteExpirationRelativeToNow); + Task SetAsync(string key, TValue value, DistributedCacheEntryOptions options, CancellationToken token = default); + Task SetAsync(string key, TValue value, TimeSpan? absoluteExpirationRelativeToNow, CancellationToken token = default); + } +} diff --git a/WorkFlowCore/Commons/Common.Caching/IDistributedCache.cs b/WorkFlowCore/Commons/Common.Caching/IDistributedCache.cs deleted file mode 100644 index be5c8990bccbcf693c132b6eb21503f320acea35..0000000000000000000000000000000000000000 --- a/WorkFlowCore/Commons/Common.Caching/IDistributedCache.cs +++ /dev/null @@ -1,340 +0,0 @@ -using System; -using JetBrains.Annotations; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Collections.Generic; -using Microsoft.Extensions.Caching.Distributed; - -namespace Common.Caching -{ - //这个接口借鉴 abp - - /// - /// Represents a distributed cache of type. - /// - /// The type of cache item being cached. - public interface IDistributedCache : IDistributedCache - where TCacheItem : class - { - } - - /// - /// Represents a distributed cache of type. - /// Uses a generic cache key type of type. - /// - /// The type of cache item being cached. - /// The type of cache key being used. - public interface IDistributedCache - where TCacheItem : class - { - /// - /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The cache item, or null. - TCacheItem Get( - TCacheKey key, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Gets multiple cache items with the given keys. - /// - /// The returned list contains exactly the same count of items specified in the given keys. - /// An item in the return list can not be null, but an item in the list has null value - /// if the related key not found in the cache. - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// List of cache items. - KeyValuePair[] GetMany( - IEnumerable keys, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Gets multiple cache items with the given keys. - /// - /// The returned list contains exactly the same count of items specified in the given keys. - /// An item in the return list can not be null, but an item in the list has null value - /// if the related key not found in the cache. - /// - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// /// The for the task. - /// List of cache items. - Task[]> GetManyAsync( - IEnumerable keys, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The cache item, or null. - Task GetAsync( - [NotNull] TCacheKey key, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item - /// provided by delegate and returns the provided cache item. - /// - /// The key of cached item to be retrieved from the cache. - /// The factory delegate is used to provide the cache item when no cache item is found for the given . - /// The cache options for the factory delegate. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The cache item. - TCacheItem GetOrAdd( - TCacheKey key, - Func factory, - Func optionsFactory = null, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item - /// provided by delegate and returns the provided cache item. - /// - /// The key of cached item to be retrieved from the cache. - /// The factory delegate is used to provide the cache item when no cache item is found for the given . - /// The cache options for the factory delegate. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The cache item. - Task GetOrAddAsync( - [NotNull] TCacheKey key, - Func> factory, - Func optionsFactory = null, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Gets or Adds multiple cache items with the given keys. If any cache items not found for the given keys then adds cache items - /// provided by delegate and returns the provided cache items. - /// - /// The keys of cached items to be retrieved from the cache. - /// The factory delegate is used to provide the cache items when no cache items are found for the given . - /// The cache options for the factory delegate. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The cache items. - KeyValuePair[] GetOrAddMany( - IEnumerable keys, - Func, List>> factory, - Func optionsFactory = null, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Gets or Adds multiple cache items with the given keys. If any cache items not found for the given keys then adds cache items - /// provided by delegate and returns the provided cache items. - /// - /// The keys of cached items to be retrieved from the cache. - /// The factory delegate is used to provide the cache items when no cache items are found for the given . - /// The cache options for the factory delegate. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The cache items. - Task[]> GetOrAddManyAsync( - IEnumerable keys, - Func, Task>>> factory, - Func optionsFactory = null, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Sets the cache item value for the provided key. - /// - /// The key of cached item to be retrieved from the cache. - /// The cache item value to set in the cache. - /// The cache options for the value. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - void Set( - TCacheKey key, - TCacheItem value, - DistributedCacheEntryOptions options = null, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Sets the cache item value for the provided key. - /// - /// The key of cached item to be retrieved from the cache. - /// The cache item value to set in the cache. - /// The cache options for the value. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task SetAsync( - [NotNull] TCacheKey key, - [NotNull] TCacheItem value, - [CanBeNull] DistributedCacheEntryOptions options = null, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Sets multiple cache items. - /// Based on the implementation, this can be more efficient than setting multiple items individually. - /// - /// Items to set on the cache - /// The cache options for the value. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - void SetMany( - IEnumerable> items, - DistributedCacheEntryOptions options = null, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Sets multiple cache items. - /// Based on the implementation, this can be more efficient than setting multiple items individually. - /// - /// Items to set on the cache - /// The cache options for the value. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task SetManyAsync( - IEnumerable> items, - DistributedCacheEntryOptions options = null, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - void Refresh( - TCacheKey key, - bool? hideErrors = null - ); - - /// - /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task RefreshAsync( - TCacheKey key, - bool? hideErrors = null, - CancellationToken token = default - ); - - /// - /// Refreshes the cache value of the given keys, and resets their sliding expiration timeout. - /// Based on the implementation, this can be more efficient than setting multiple items individually. - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - void RefreshMany( - IEnumerable keys, - bool? hideErrors = null); - - /// - /// Refreshes the cache value of the given keys, and resets their sliding expiration timeout. - /// Based on the implementation, this can be more efficient than setting multiple items individually. - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task RefreshManyAsync( - IEnumerable keys, - bool? hideErrors = null, - CancellationToken token = default); - - /// - /// Removes the cache item for given key from cache. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - void Remove( - TCacheKey key, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Removes the cache item for given key from cache. - /// - /// The key of cached item to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task RemoveAsync( - TCacheKey key, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - - /// - /// Removes the cache items for given keys from cache. - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - void RemoveMany( - IEnumerable keys, - bool? hideErrors = null, - bool considerUow = false - ); - - /// - /// Removes the cache items for given keys from cache. - /// - /// The keys of cached items to be retrieved from the cache. - /// Indicates to throw or hide the exceptions for the distributed cache. - /// This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache. - /// The for the task. - /// The indicating that the operation is asynchronous. - Task RemoveManyAsync( - IEnumerable keys, - bool? hideErrors = null, - bool considerUow = false, - CancellationToken token = default - ); - } -} diff --git a/WorkFlowCore/Commons/Common.DependencyInjection/Common.DependencyInjection.csproj b/WorkFlowCore/Commons/Common.DependencyInjection/Common.DependencyInjection.csproj index 9393460b6f9fa6733fc8a7884ea63078d0dd4e3a..0a57e3edfee894540fe2fdcedb0f98cd273e2006 100644 --- a/WorkFlowCore/Commons/Common.DependencyInjection/Common.DependencyInjection.csproj +++ b/WorkFlowCore/Commons/Common.DependencyInjection/Common.DependencyInjection.csproj @@ -9,6 +9,7 @@ + diff --git a/WorkFlowCore/Commons/Common.DependencyInjection/DependencyInjectionModule.cs b/WorkFlowCore/Commons/Common.DependencyInjection/DependencyInjectionModule.cs index 161a9bb0ec0d132efff3785e897879defd1ba31d..052cfba0148978240988b26fc93822920aa95f98 100644 --- a/WorkFlowCore/Commons/Common.DependencyInjection/DependencyInjectionModule.cs +++ b/WorkFlowCore/Commons/Common.DependencyInjection/DependencyInjectionModule.cs @@ -1,10 +1,12 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; + namespace Common.DependencyInjection { public static class DependencyInjectionModule diff --git a/WorkFlowCore/Commons/Common.DependencyInjection/GlobalServiceProvider.cs b/WorkFlowCore/Commons/Common.DependencyInjection/GlobalServiceProvider.cs new file mode 100644 index 0000000000000000000000000000000000000000..f367f9aa3a1a5b1959bbca0518bee91515382bbd --- /dev/null +++ b/WorkFlowCore/Commons/Common.DependencyInjection/GlobalServiceProvider.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DependencyInjection +{ + public class GlobalServiceProvider + { + private static IServiceProvider ServiceProvider; + + public static void Init(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public static IServiceProvider Current { get => ServiceProvider; } + } +} diff --git a/WorkFlowCore/Commons/Common.DistributedLock.Redis/Common.DistributedLock.Redis.csproj b/WorkFlowCore/Commons/Common.DistributedLock.Redis/Common.DistributedLock.Redis.csproj new file mode 100644 index 0000000000000000000000000000000000000000..8a211141afefa84984f018a14198a0e51f122b41 --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock.Redis/Common.DistributedLock.Redis.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisConfigure.cs b/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisConfigure.cs new file mode 100644 index 0000000000000000000000000000000000000000..f237c8c2ef44d0b35aed0da1ca6829f40e7d333e --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisConfigure.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock.Redis +{ + public class CommonDistributedLockRedisConfigure + { + /// + /// redis 链接字符串 + /// 为了实现分布式场景下定时任务不同时运行 + /// + public string RedisConnectionString { get; set; } + } +} diff --git a/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisModule.cs b/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..36bf53e6b55cb792d3735d0725da13dc3fdc15b1 --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock.Redis/CommonDistributedLockRedisModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock.Redis +{ + public static class CommonDistributedLockRedisModule + { + + /// + public static IServiceCollection AddDistributedLock(this IServiceCollection services,Action options) + { + var config = new CommonDistributedLockRedisConfigure(); + options?.Invoke(config); + services.AddSingleton(config); + services.AddDistributedLock(); + return services; + } + } +} diff --git a/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/DistributiveLock.cs b/WorkFlowCore/Commons/Common.DistributedLock.Redis/DistributedLock.cs similarity index 39% rename from WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/DistributiveLock.cs rename to WorkFlowCore/Commons/Common.DistributedLock.Redis/DistributedLock.cs index d08b08a9c14702027a79549af2cb0c43d6a42ceb..69edff9d808a00cfd002d32a5d9cbe23f7b95d38 100644 --- a/WorkFlowCore/Commons/Common.BackgroundWorker/QuartzImplement/DistributiveLock.cs +++ b/WorkFlowCore/Commons/Common.DistributedLock.Redis/DistributedLock.cs @@ -2,23 +2,31 @@ using System; using System.Collections.Generic; using System.Text; +using Common.DistributedLock; +using System.Threading; -namespace Common.BackgroundWorker.QuartzImplement +namespace Common.DistributedLock.Redis { /// /// 分布式锁 /// - public class DistributiveLock + public class DistributedLock: DistributedLockBase { + private readonly CommonDistributedLockRedisConfigure redisConfigure; private IDatabase db; + - public DistributiveLock(QuartzWorkerConfig quartzWorkerConfig) + public DistributedLock(CommonDistributedLockRedisConfigure redisConfigure) { - //TODO 增加链接判断以及创建异常重拾处理 + this.redisConfigure = redisConfigure; + Connect(); + } + private void Connect() + { try { - var redisMultiplexer = ConnectionMultiplexer.Connect(quartzWorkerConfig.RedisConnectionString); + var redisMultiplexer = ConnectionMultiplexer.Connect(redisConfigure.RedisConnectionString); db = redisMultiplexer.GetDatabase(); } catch (Exception ex) @@ -27,6 +35,7 @@ namespace Common.BackgroundWorker.QuartzImplement } } + public bool Lock(string key,TimeSpan? timeSpan) { if (db == null) return true;//如果没有指定redis,默认通过, @@ -41,11 +50,36 @@ namespace Common.BackgroundWorker.QuartzImplement } } - public bool Unlock(string key) + public override bool Lock(TimeSpan? expiredTime, TimeSpan? timeout) { - if (db == null) return true; - return db.KeyDelete(key); + var time = 0; + while (!CanLock(expiredTime)) + { + if (timeout.HasValue && timeout.Value.TotalSeconds <= time) return false; + time += 100; + Thread.Sleep(100); + } + return true; + } + + public override bool CanLock(TimeSpan? expiredTime) + { + if (db == null) return false;//如果没有指定redis,默认通过, + try + { + var result = db.StringSet(LockKey, "locked", expiredTime, When.NotExists); + return result; + } + catch (Exception ex) + { + return false; + } } + public override bool Unlock() + { + if (db == null) return false; + return db.KeyDelete(LockKey); + } } } diff --git a/WorkFlowCore/Commons/Common.DistributedLock/Common.DistributedLock.csproj b/WorkFlowCore/Commons/Common.DistributedLock/Common.DistributedLock.csproj new file mode 100644 index 0000000000000000000000000000000000000000..7a65c7aa4acccb2521aff1c55d713be62e35c4d1 --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock/Common.DistributedLock.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/WorkFlowCore/Commons/Common.DistributedLock/CommonDistributedLockModule.cs b/WorkFlowCore/Commons/Common.DistributedLock/CommonDistributedLockModule.cs new file mode 100644 index 0000000000000000000000000000000000000000..dcfb81ee938f560408573e1b26b23594e4a4bdb7 --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock/CommonDistributedLockModule.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock +{ + public static class CommonDistributedLockModule + { + /// + /// + /// + /// TDistributiveLock 需要支持瞬时注入 + /// + /// + public static IServiceCollection AddDistributedLock(this IServiceCollection services)where TDistributiveLock: DistributedLockBase + { + services.AddTransient(); + return services; + } + + } +} diff --git a/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockBase.cs b/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..f634f5baedd41fd5ac8bb7b9a094a929d73dddbd --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockBase.cs @@ -0,0 +1,77 @@ +using Common.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock +{ + /// + /// 分布式锁 + /// + public abstract class DistributedLockBase : IDistributedLock, ITransientService + { + /// + /// 锁定key + /// + public string LockKey { get;internal set; } + /// + /// 锁定,如果一时无法锁定,则等待 + /// + /// 自动过期时间 + /// 超时时间,若指定,则在超时后不再等待 + /// + public abstract bool Lock(TimeSpan? expiredTime,TimeSpan? timeout); + + /// + /// 执行锁逻辑,自动调用释放 + /// + /// 在锁内部执行的逻辑 + /// 自动过期时间 + /// 超时时间,若指定,则在超时后不再等待 + public void Lock(Action action,TimeSpan? expiredTime,TimeSpan? timeout) + { + Lock(expiredTime, timeout); + try + { + action?.Invoke(); + } + finally + { + Unlock(); + } + } + /// + /// 尝试锁,锁定失败则不管 + /// + /// 自动过期时间 + /// + public abstract bool CanLock(TimeSpan? expiredTime); + + /// + /// 如果锁定成功则执行锁逻辑 + /// + /// + /// + /// + public void CanLock(Action action, TimeSpan? expiredTime) + { + if(CanLock(expiredTime)) + { + try + { + action?.Invoke(); + } + finally + { + Unlock(); + } + } + } + /// + /// 解锁 + /// + /// + public abstract bool Unlock(); + + } +} diff --git a/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockManager.cs b/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..78d559e98235764f4ecf2dac4acc01334d81b985 --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock/DistributedLockManager.cs @@ -0,0 +1,25 @@ +using Common.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock +{ + public class DistributedLockManager + { + public static IDistributedLock NewLock(string lockKey) + { + + if(string.IsNullOrEmpty(lockKey)) throw new ArgumentNullException(nameof(lockKey)); + var _key = $"DistributedLock_{lockKey}"; + using (var scope = GlobalServiceProvider.Current.CreateScope()) + { + var lockObj = scope.ServiceProvider.GetService(); + lockObj.LockKey= _key; + return lockObj; + } + } + + } +} diff --git a/WorkFlowCore/Commons/Common.DistributedLock/IDistributedLock.cs b/WorkFlowCore/Commons/Common.DistributedLock/IDistributedLock.cs new file mode 100644 index 0000000000000000000000000000000000000000..d3fe4314aed88e0d0966085fef1daf670366b1bf --- /dev/null +++ b/WorkFlowCore/Commons/Common.DistributedLock/IDistributedLock.cs @@ -0,0 +1,49 @@ +using Common.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Common.DistributedLock +{ + /// + /// 分布式锁 + /// + public interface IDistributedLock : ITransientService + { + /// + /// 锁定,如果一时无法锁定,则等待 + /// + /// 自动过期时间 + /// 超时时间,若指定,则在超时后不再等待 + /// + bool Lock(TimeSpan? expiredTime,TimeSpan? timeout); + + /// + /// 执行锁逻辑,自动调用释放 + /// + /// 在锁内部执行的逻辑 + /// 自动过期时间 + /// 超时时间,若指定,则在超时后不再等待 + void Lock(Action action, TimeSpan? expiredTime, TimeSpan? timeout); + /// + /// 尝试锁,锁定失败则不管 + /// + /// 自动过期时间 + /// + bool CanLock(TimeSpan? expiredTime); + + /// + /// 如果锁定成功则执行锁逻辑 + /// + /// + /// + /// + void CanLock(Action action, TimeSpan? expiredTime); + /// + /// 解锁 + /// + /// + public abstract bool Unlock(); + + } +} diff --git a/WorkFlowCore/Commons/Common.EventBus/Common.EventBus.csproj b/WorkFlowCore/Commons/Common.EventBus/Common.EventBus.csproj index 2991563f7f25e231051ab340e95061b0715747e9..0e20fbfebe8cbbc73f412ab74417d8f62a99045f 100644 --- a/WorkFlowCore/Commons/Common.EventBus/Common.EventBus.csproj +++ b/WorkFlowCore/Commons/Common.EventBus/Common.EventBus.csproj @@ -14,6 +14,7 @@ + diff --git a/WorkFlowCore/Commons/Common.EventBus/CommonEventBusModule.cs b/WorkFlowCore/Commons/Common.EventBus/CommonEventBusModule.cs index 9474aa81ba7ffc02e43582cd2594991eb1103031..40a1fb39f67961a06839e5a5ecff66d1cac4492e 100644 --- a/WorkFlowCore/Commons/Common.EventBus/CommonEventBusModule.cs +++ b/WorkFlowCore/Commons/Common.EventBus/CommonEventBusModule.cs @@ -18,13 +18,6 @@ namespace Common.EventBus return services; } - public static IApplicationBuilder RunEventBus(this IApplicationBuilder app) - { - //注册普通事件,该事件订阅在单应用有效无法分布式 - DomainEventBusManager.Init(app.ApplicationServices); - return app; - - } /// /// 在 UseUnitOfWork之前执行; /// @@ -33,7 +26,6 @@ namespace Common.EventBus public static IApplicationBuilder UseEventBus(this IApplicationBuilder app) { //注册普通事件,该事件订阅在单应用有效无法分布式 - DomainEventBusManager.Init(app.ApplicationServices); app.UseMiddleware(); return app; diff --git a/WorkFlowCore/Commons/Common.EventBus/DomainEventBusManager.cs b/WorkFlowCore/Commons/Common.EventBus/DomainEventBusManager.cs index a9248e4c7623b9685f221dba3987ac298f7005de..fb6a7aea306d42520a4acd0dfbb1ad440ec40cea 100644 --- a/WorkFlowCore/Commons/Common.EventBus/DomainEventBusManager.cs +++ b/WorkFlowCore/Commons/Common.EventBus/DomainEventBusManager.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using Common.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Text; @@ -10,15 +11,13 @@ namespace Common.EventBus /// public class DomainEventBusManager { - private static IServiceProvider serviceProvider; - internal static void Init(IServiceProvider serviceProvider) - { - DomainEventBusManager.serviceProvider = serviceProvider; - } - + public static IEventBus EventBusInstance() { - return serviceProvider.CreateScope().ServiceProvider.GetService(); + using (var scope = GlobalServiceProvider.Current.CreateScope()) + { + return scope.ServiceProvider.GetService(); + } } } } diff --git a/WorkFlowCore/Commons/Common.IBaseRepositories/ICreationEntity.cs b/WorkFlowCore/Commons/Common.IBaseRepositories/ICreationEntity.cs index d3edf35d76ca8c602521e0639b665eb39e2b88dd..6adf78ed1c3ca72db360f3725f154657a27558c6 100644 --- a/WorkFlowCore/Commons/Common.IBaseRepositories/ICreationEntity.cs +++ b/WorkFlowCore/Commons/Common.IBaseRepositories/ICreationEntity.cs @@ -4,7 +4,7 @@ using System.Text; namespace Common.IBaseRepositories { - public interface ICreationEntity + public interface ICreationEntity : IEntity { /// /// 创建用户 diff --git a/WorkFlowCore/Commons/Common.IBaseRepositories/IModificationEntity.cs b/WorkFlowCore/Commons/Common.IBaseRepositories/IModificationEntity.cs index 77b4fd0959b42d085864f9acadedece265bcf3c9..0381b1698243424012087083e8335ae430475dc5 100644 --- a/WorkFlowCore/Commons/Common.IBaseRepositories/IModificationEntity.cs +++ b/WorkFlowCore/Commons/Common.IBaseRepositories/IModificationEntity.cs @@ -4,7 +4,7 @@ using System.Text; namespace Common.IBaseRepositories { - public interface IModificationEntity + public interface IModificationEntity:IEntity { /// /// 更新时间 diff --git a/WorkFlowCore/Commons/Common.IBaseRepositories/ISoftDeleteEntity.cs b/WorkFlowCore/Commons/Common.IBaseRepositories/ISoftDeleteEntity.cs index bad794d32186cc0bf20ba454c79480fa280c0142..8dba391504596dc372e585ede33c12828f77a32f 100644 --- a/WorkFlowCore/Commons/Common.IBaseRepositories/ISoftDeleteEntity.cs +++ b/WorkFlowCore/Commons/Common.IBaseRepositories/ISoftDeleteEntity.cs @@ -4,7 +4,7 @@ using System.Text; namespace Common.IBaseRepositories { - public interface ISoftDeleteEntity + public interface ISoftDeleteEntity : IEntity { /// /// 删除用户 diff --git a/WorkFlowCore/Commons/Common.IBaseRepositories4EF/IBasicRepository4EF.cs b/WorkFlowCore/Commons/Common.IBaseRepositories4EF/IBasicRepository4EF.cs index ca5d75d3b5aada925a3129fe2ca1fe0dd5776636..5e2ab3e6982aa0606c5c423c08e0656a84bd79ec 100644 --- a/WorkFlowCore/Commons/Common.IBaseRepositories4EF/IBasicRepository4EF.cs +++ b/WorkFlowCore/Commons/Common.IBaseRepositories4EF/IBasicRepository4EF.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Common.IBaseRepositories4EF { - public interface IBasicRepository4EF : IBasicRepository, IReadOnlyBasicRepository, ISoftDeleteRepository where TEntity : class, IEntity + public interface IBasicRepository4EF : IBasicRepository, IReadOnlyBasicRepository/*, ISoftDeleteRepository*/ where TEntity : class, IEntity { Task> GetListAsync( List conditions, diff --git a/WorkFlowCore/Commons/Common.MicroService/Registers/Consul.cs b/WorkFlowCore/Commons/Common.MicroService/Registers/Consul.cs index e0315aa2a6cad2aceefe95e2a73c0a6bbd9883fd..345b2f1c8569b337bce2b3f7285b2831f8bae98a 100644 --- a/WorkFlowCore/Commons/Common.MicroService/Registers/Consul.cs +++ b/WorkFlowCore/Commons/Common.MicroService/Registers/Consul.cs @@ -35,10 +35,10 @@ namespace Common.MicroService.Registers }); - var ip = _options.ServiceIP; + //var ip = _options.ServiceIP; var port = _options.ServicePort; var serviceName = _options.ServiceName; - Console.WriteLine($"args:{ip},{port},{serviceName}"); + //Console.WriteLine($"args:{ip},{port},{serviceName}"); var addresses = NetworkInterface.GetAllNetworkInterfaces() diff --git a/WorkFlowCore/DynamicForm/DynamicForm.AppService/DynamicForm.AppService.csproj b/WorkFlowCore/DynamicForm/DynamicForm.AppService/DynamicForm.AppService.csproj index f5607d8e8037e543ea8f4b77fd28f64f9d2b0089..dc92087242e2921fb1ccb50721ef7be4e7ea35c6 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.AppService/DynamicForm.AppService.csproj +++ b/WorkFlowCore/DynamicForm/DynamicForm.AppService/DynamicForm.AppService.csproj @@ -9,6 +9,7 @@ + diff --git a/WorkFlowCore/DynamicForm/DynamicForm.AppService/FormInstances/FormInstanceAppService.cs b/WorkFlowCore/DynamicForm/DynamicForm.AppService/FormInstances/FormInstanceAppService.cs index 44c9525cee8d082df84a64b8c754a1b390939edc..d5b0055160c8b71c2510e603539c0e4ae4e25304 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.AppService/FormInstances/FormInstanceAppService.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.AppService/FormInstances/FormInstanceAppService.cs @@ -1,11 +1,13 @@ using Common.AppService.Implements; using Common.Authorization; +using Common.Caching; using Common.EventBus; using Common.IBaseRepositories; using Common.IBaseRepositories4EF; using Common.WebApi.ViewModels; using DynamicForm.Core; using DynamicForm.Core.FormInstances; +using DynamicForm.Core.Workflows; using DynamicForm.IAppService.FormInstances; using DynamicForm.IAppService.FormInstances.Dto; using Mapster; @@ -24,19 +26,22 @@ namespace DynamicForm.AppService.FormInstances private readonly FormInstanceManager formInstanceManager; private readonly ICommonSession commonSession; private readonly IBasicRepository4EF designRepository; + private readonly IBasicRepository workflowVersionRepository; + private readonly ICommonCache commonCache; - public FormInstanceAppService(IBasicRepository4EF repository, FormInstanceManager formInstanceManager,ICommonSession commonSession, IBasicRepository4EF designRepository) : base(repository) + public FormInstanceAppService(IBasicRepository4EF repository, FormInstanceManager formInstanceManager, ICommonSession commonSession, IBasicRepository4EF designRepository, IBasicRepository workflowVersionRepository, ICommonCache commonCache) : base(repository) { this.repository = repository; this.formInstanceManager = formInstanceManager; this.commonSession = commonSession; this.designRepository = designRepository; + this.workflowVersionRepository = workflowVersionRepository; + this.commonCache = commonCache; } public override async Task CreateAsync(FormInstanceCreateInput input) { - var instance = new FormInstance(input.FormDesignId, input.WorkflowId, input.FormData, input.Title); - await repository.InsertAsync(instance.ToFormInstanceInfo()); + var instance = await formInstanceManager.CreateFormInstance(input.FormDesignId, input.WorkflowId, input.FormData, input.Title, commonSession?.User?.Id); return instance.Adapt(); } public override async Task UpdateAsync(Guid id, FormInstanceUpdateInput input) @@ -66,7 +71,7 @@ namespace DynamicForm.AppService.FormInstances } public async Task> GetPageListOfCurrentUserAsync([FromQuery] GetPageResultInput input) { - var count = await repository.GetCountAsync(input.Conditions); + var count = await repository.GetCountAsync(input.Conditions, f => f.CreatedUserId == commonSession.User.Id); var entities = await repository.GetPagedListAsync(input.Conditions, f => f.CreatedUserId == commonSession.User.Id, input.SkipCount, input.MaxResultCount, input.Sorting); var items = entities.Select(e => e.ToFormInstance()).Adapt>(); @@ -79,14 +84,13 @@ namespace DynamicForm.AppService.FormInstances { var formDesignIds = items.Select(e => e.FormDesignId.Id).Distinct().ToList(); var formDesigns = await designRepository.GetListAsync(d => formDesignIds.Contains(d.Id)); - var formDesignNameMap = formDesigns.GroupBy(f => f.Id).ToDictionary(g => g.Key, g => g.FirstOrDefault().Title); - - + var workflows = await workflowVersionRepository.GetListAsync(w => items.Select(i => i.WorkflowId.Id).Contains(w.WorkflowId)); items.ForEach(e => { e.FormDesignTitle = formDesignNameMap.ContainsKey(e.FormDesignId.Id) ? formDesignNameMap[e.FormDesignId.Id] : ""; + e.WorkflowId.WorkflowName = workflows.FirstOrDefault(w=>w.WorkflowId==e.WorkflowId.Id&&w.VersionNo==e.WorkflowId.Version)?.WorkflowName; }); } @@ -95,9 +99,10 @@ namespace DynamicForm.AppService.FormInstances var entity = await repository.GetAsync(i => i.Id.Equals(id)); return entity.ToFormInstance().Adapt(); } - public async Task CreateAndStartWorkTask(Guid id) + + public async Task StartWorkTask(StartWorkTaskInput startWorkTaskInput) { - return await formInstanceManager.CreateAndStartWorkTask(id); + return await formInstanceManager.StartWorkTask(startWorkTaskInput.FormInstanceId, startWorkTaskInput.WorkTaskId); } } } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Core/DynamicFormCoreModule.cs b/WorkFlowCore/DynamicForm/DynamicForm.Core/DynamicFormCoreModule.cs index da5a2924a52a1498b0a9cb11917e2225b2c6fa3a..1d6357c5d6b475b109ec037eb72bb7d350d966d2 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Core/DynamicFormCoreModule.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.Core/DynamicFormCoreModule.cs @@ -27,7 +27,10 @@ namespace DynamicForm.Core }); services.AddDependencyServices(Assembly.GetExecutingAssembly()); - + + //注册后台工作者 + services.AddBackgroundWorker(serviceConfig.BackgroundWorkerRedisConnectionString, Assembly.GetExecutingAssembly()); + return services; } } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Core/FormDesigns/FormDesignInterface.cs b/WorkFlowCore/DynamicForm/DynamicForm.Core/FormDesigns/FormDesignInterface.cs new file mode 100644 index 0000000000000000000000000000000000000000..512aed4dad15f78eeed22234b5c11d03f05dd9f1 --- /dev/null +++ b/WorkFlowCore/DynamicForm/DynamicForm.Core/FormDesigns/FormDesignInterface.cs @@ -0,0 +1,30 @@ +using Common.DependencyInjection; +using Common.IBaseRepositories; +using DynamicForm.Core.Workflows; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DynamicForm.Core.FormDesigns +{ + public class FormDesignInterface : IScopedService + { + private readonly IBasicRepository formDesignRepository; + private readonly IBasicRepository formDesignVersionRepository; + private readonly WorkflowAdapter workflowAdapter; + + public FormDesignInterface(IBasicRepository formDesignRepository, IBasicRepository formDesignVersionRepository, WorkflowAdapter workflowAdapter) + { + this.formDesignRepository = formDesignRepository; + this.formDesignVersionRepository = formDesignVersionRepository; + this.workflowAdapter = workflowAdapter; + } + + public async Task GetFormDesignVersion(FormDesignId formDesignId) + { + return await formDesignVersionRepository.GetAsync(f => f.FormDesignId == formDesignId.Id && f.Version == formDesignId.Version); + } + } +} diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Core/FormInstances/FormInstanceManager.cs b/WorkFlowCore/DynamicForm/DynamicForm.Core/FormInstances/FormInstanceManager.cs index a7dc7c992cada879202abdfd7a36b8bfe8e28e90..357499ebe0ffbe138b7f714735a5f70e8d5979ee 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Core/FormInstances/FormInstanceManager.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.Core/FormInstances/FormInstanceManager.cs @@ -43,16 +43,23 @@ namespace DynamicForm.Core.FormInstances await formInstanceInfoRepository.DeleteAsync(instance.ToFormInstanceInfo(instanceInfo)); return instance; } + public async Task CreateFormInstance(FormDesignId formDesignId, WorkflowId workflowId, string formData, string title,string creator) + { + var instance = new FormInstance(formDesignId, workflowId, formData, title); + await formInstanceInfoRepository.InsertAsync(instance.ToFormInstanceInfo()); + + await workflowAdapter.CreateWorkTask(new Workflows.WorkflowId(workflowId.Version,workflowId.Id), title, formData, typeof(FormInstance).FullName, instance.Id.ToString(), creator); + + return instance; + } + - public async Task CreateAndStartWorkTask(Guid formInstanceId) + public async Task StartWorkTask(Guid formInstanceId,Guid workTaskId) { var instanceInfo = await formInstanceInfoRepository.GetAsync(f => f.Id == formInstanceId); + var instance = instanceInfo.ToFormInstance(); - var started = await workflowAdapter.CreateAndStartWorkTask(new Workflows.WorkflowId - { - Id = instance.WorkflowId.Id, - VersionId = instance.WorkflowId.Version, - }, instance.Title, instance.FormData, instance.GetType().FullName, instance.Id.ToString(), instance.CreatedUserId); + var started = await workflowAdapter.StartWorkTask(workTaskId.ToString(), instance.FormData); if (started) { instance.Processing(); diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowAdapter.cs b/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowAdapter.cs index 3990460791a7538a213f9ed45071d40dfe1209fb..b929a34ba6c15c99c2977a4ba5466d14c3cc5757 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowAdapter.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowAdapter.cs @@ -19,9 +19,9 @@ namespace DynamicForm.Core.Workflows this.webApiClient = webApiClient; } - public async Task CreateAndStartWorkTask(WorkflowId WorkflowId, string Name, string FormData, string EntityFullName, string EntityKeyValue, string CreatedUserId) + public async Task CreateWorkTask(WorkflowId WorkflowId, string Name, string FormData, string EntityFullName, string EntityKeyValue, string CreatedUserId) { - var result = await webApiClient.PostAsync, object>("workflow/api/workflow/CreateAndStartWorkTask", new + var result = await webApiClient.PostAsync, object>("workflow/api/workflow/CreateWorkTask", new { WorkflowId = new { @@ -38,11 +38,18 @@ namespace DynamicForm.Core.Workflows if (result == null || !result.IsSucced) throw new Exception(result?.Msg ?? "创建工作流任务失败!"); + return true; + } + + public async Task StartWorkTask(string WorktaskId, string formData) + { var startResult = await webApiClient.PostAsync, object>("workflow/api/workflow/StartWorkTask", new { - WorktaskId = result.Data.id.ToString(), + FormData = formData, + WorktaskId = WorktaskId, }, false); ; - + if (startResult == null || !startResult.IsSucced) + throw new Exception(startResult?.Msg ?? "创建工作流任务失败!"); return true; } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowInterface.cs b/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowInterface.cs index 99567cad2c3010ab423b76cc206aa01456d73403..c8f544b58defcfdf634898dacf2cf43edfd724fb 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowInterface.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.Core/Workflows/WorkflowInterface.cs @@ -30,5 +30,11 @@ namespace DynamicForm.Core.Workflows repository.InsertAsync(currentVersion).Wait(); } } + + public async Task GetWorkflowVersionByWorkflowId(WorkflowId workflowId) + { + var currentVersion = repository.GetAsync(v => v.WorkflowId == workflowId.Id && v.VersionNo == workflowId.VersionId).Result; + return currentVersion; + } } } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Host/DynamicForm.Host.csproj b/WorkFlowCore/DynamicForm/DynamicForm.Host/DynamicForm.Host.csproj index c1e9c52fe7bbaf2d0157bcc94999a19dfe86e94c..6bcbd8efbeb902250c846f8a0b5343400a0a8b43 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Host/DynamicForm.Host.csproj +++ b/WorkFlowCore/DynamicForm/DynamicForm.Host/DynamicForm.Host.csproj @@ -22,7 +22,9 @@ + + diff --git a/WorkFlowCore/DynamicForm/DynamicForm.Host/Startup.cs b/WorkFlowCore/DynamicForm/DynamicForm.Host/Startup.cs index 215ad4b4dae8dbdf6b482768896615f16dc35663..71eea943a3a7e4182b53972737622aeab7dc4e27 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.Host/Startup.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.Host/Startup.cs @@ -1,5 +1,9 @@ using Common.BackgroundWorker; +using Common.Caching.Redis; +using Common.DependencyInjection; +using Common.DistributedLock; +using Common.DistributedLock.Redis; using Common.DynamicApi; using Common.EventBus; using Common.EventBus.Kafka; @@ -63,6 +67,20 @@ namespace DynamicForm.Host }); + services.AddDistributedLock(options => + { + options.RedisConnectionString = Configuration.GetValueFromManyChanels("BackgroundWorker:RedisConnectionString"); + + }); + + services.AddCommonCachingRedis(options => + { + options.RedisConnectionString = Configuration.GetValueFromManyChanels("BackgroundWorker:RedisConnectionString"); + + }); + + + services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "DynamicForm.Host", Version = "v1" }); @@ -131,6 +149,8 @@ namespace DynamicForm.Host //̨ app.RunBackgroundWorker(); + + GlobalServiceProvider.Init(app.ApplicationServices); } } } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/FormInstanceDto.cs b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/FormInstanceDto.cs index 329345cddf25d36d2c799df74eb0d080ecf29d72..9baae5af812692be4ed71f90be728f13c3cfa0eb 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/FormInstanceDto.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/FormInstanceDto.cs @@ -11,7 +11,7 @@ namespace DynamicForm.IAppService.FormInstances.Dto { public FormDesignId FormDesignId { get; set; } public string FormDesignTitle { get; set; } - public WorkflowId WorkflowId { get; set; } + public WorkflowIdDto WorkflowId { get; set; } public string Title { get; set; } public string FormData { get; set; } public WorkTaskStatus WorkflowStatus { get; set; } diff --git a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/StartWorkTaskInput.cs b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/StartWorkTaskInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..3a81f6f5b1b3d7cd72afa90f7267f0bfb2ac9ed0 --- /dev/null +++ b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/StartWorkTaskInput.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DynamicForm.IAppService.FormInstances.Dto +{ + public class StartWorkTaskInput + { + public Guid FormInstanceId { get; set; } + public Guid WorkTaskId { get; set; } + } +} diff --git a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/WorkflowIdDto.cs b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/WorkflowIdDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..eb0ad2272a46ae3da4c5cafe749a9fbe88255cef --- /dev/null +++ b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/Dto/WorkflowIdDto.cs @@ -0,0 +1,15 @@ +using DynamicForm.Core; +using System; +using System.Collections.Generic; +using System.Text; + +namespace DynamicForm.IAppService.FormInstances.Dto +{ + public class WorkflowIdDto : WorkflowId + { + /// + /// 流程名称 + /// + public string WorkflowName { get; set; } + } +} diff --git a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/IFormInstanceAppService.cs b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/IFormInstanceAppService.cs index 0aa2d9c5faf442fee82e577a70d9bbe9ed89323d..d87a3e89f1a49fd0b8abb69626cd09351d90185c 100644 --- a/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/IFormInstanceAppService.cs +++ b/WorkFlowCore/DynamicForm/DynamicForm.IAppService/FormInstances/IFormInstanceAppService.cs @@ -14,6 +14,6 @@ namespace DynamicForm.IAppService.FormInstances { Task> GetPageListOfCurrentUserAsync(GetPageResultInput input); - Task CreateAndStartWorkTask(Guid id); + Task StartWorkTask(StartWorkTaskInput startWorkTaskInput); } } diff --git a/WorkFlowCore/UserOrganization/Organization.Host/Startup.cs b/WorkFlowCore/UserOrganization/Organization.Host/Startup.cs index b8ff68c6e10d31b80e2aef1833c110b97f01dac6..2a13735ec90443096fdfad5d2a73b6f681ff9f1d 100644 --- a/WorkFlowCore/UserOrganization/Organization.Host/Startup.cs +++ b/WorkFlowCore/UserOrganization/Organization.Host/Startup.cs @@ -1,6 +1,7 @@ using Common.Authorization; using Common.BackgroundWorker; using Common.BaseRepositories4EF; +using Common.DependencyInjection; using Common.DynamicApi; using Common.EventBus; using Common.EventBus.Kafka; @@ -111,8 +112,7 @@ namespace Organization.Host { endpoints.MapControllers(); }); - //ע��consul - //ע��consul + //注册consul app.RunConsulRegister(options => { options.ConsulAddress = Configuration.GetValueFromManyChanels("Consul:Address"); @@ -120,12 +120,12 @@ namespace Organization.Host options.ServiceIP = Configuration.GetValueFromManyChanels("Service:IP"); options.ServicePort = Configuration.GetValueFromManyChanels("Service:Port"); - options.ServiceName = Configuration.GetValueFromManyChanels("Service:Name"); + options.ServiceName = Configuration.GetValueFromManyChanels("Service:Name"); }, lifetime); - //ע��ȫ���¼����� - - //������̨�������� + + //开启后台工作任务 app.RunBackgroundWorker(); + GlobalServiceProvider.Init(app.ApplicationServices); } } } diff --git a/WorkFlowCore/WorkFlowCore.sln b/WorkFlowCore/WorkFlowCore.sln index 0120be88291dc7de687d3f0e5d44069b0b946494..37ddf04eef105ccf0e7401b91b3637563454a0e8 100644 --- a/WorkFlowCore/WorkFlowCore.sln +++ b/WorkFlowCore/WorkFlowCore.sln @@ -83,9 +83,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Mapster", "Commons\C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.SimplePluginLoader", "Commons\Common.SimplePluginLoader\Common.SimplePluginLoader.csproj", "{038F8892-EDB7-4091-AC59-D21DC44033E0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.EventBus.Repository4EF", "Commons\Common.EventBus.Repository4EF\Common.EventBus.Repository4EF.csproj", "{519E4805-268B-409C-9167-45A5DF4B8F69}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.EventBus.Repository4EF", "Commons\Common.EventBus.Repository4EF\Common.EventBus.Repository4EF.csproj", "{519E4805-268B-409C-9167-45A5DF4B8F69}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Caching", "Commons\Common.Caching\Common.Caching.csproj", "{A556C938-F98C-4E93-AE37-159C5DFACC0D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Caching", "Commons\Common.Caching\Common.Caching.csproj", "{A556C938-F98C-4E93-AE37-159C5DFACC0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.DistributedLock", "Commons\Common.DistributedLock\Common.DistributedLock.csproj", "{0792B52F-064E-458E-A4F2-8041A24275AC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.DistributedLock.Redis", "Commons\Common.DistributedLock.Redis\Common.DistributedLock.Redis.csproj", "{D9A19817-B7FE-4552-915C-044DAC2DA08A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Caching.Redis", "Commons\Common.Caching.Redis\Common.Caching.Redis.csproj", "{A26A600B-9FF5-4112-B90D-6D40D4E2B2F4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -241,6 +247,18 @@ Global {A556C938-F98C-4E93-AE37-159C5DFACC0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A556C938-F98C-4E93-AE37-159C5DFACC0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A556C938-F98C-4E93-AE37-159C5DFACC0D}.Release|Any CPU.Build.0 = Release|Any CPU + {0792B52F-064E-458E-A4F2-8041A24275AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0792B52F-064E-458E-A4F2-8041A24275AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0792B52F-064E-458E-A4F2-8041A24275AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0792B52F-064E-458E-A4F2-8041A24275AC}.Release|Any CPU.Build.0 = Release|Any CPU + {D9A19817-B7FE-4552-915C-044DAC2DA08A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9A19817-B7FE-4552-915C-044DAC2DA08A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9A19817-B7FE-4552-915C-044DAC2DA08A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9A19817-B7FE-4552-915C-044DAC2DA08A}.Release|Any CPU.Build.0 = Release|Any CPU + {A26A600B-9FF5-4112-B90D-6D40D4E2B2F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A26A600B-9FF5-4112-B90D-6D40D4E2B2F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A26A600B-9FF5-4112-B90D-6D40D4E2B2F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A26A600B-9FF5-4112-B90D-6D40D4E2B2F4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -283,6 +301,9 @@ Global {038F8892-EDB7-4091-AC59-D21DC44033E0} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} {519E4805-268B-409C-9167-45A5DF4B8F69} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} {A556C938-F98C-4E93-AE37-159C5DFACC0D} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} + {0792B52F-064E-458E-A4F2-8041A24275AC} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} + {D9A19817-B7FE-4552-915C-044DAC2DA08A} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} + {A26A600B-9FF5-4112-B90D-6D40D4E2B2F4} = {3EF58BFB-DEAB-4607-9C83-3D0B0BF0CFFA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2B47C6B7-D14F-4E7A-AC89-493A7F10350B} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.AppService/WorkFlowCores/WorkFlowAppService.cs b/WorkFlowCore/Workflow/WorkFlowCore.AppService/WorkFlowCores/WorkFlowAppService.cs index 6bfcb33abb0ee0edcd0f60f5faa19b18a794404f..87cf46fc52e74e30da2d8a4961abd5414681d77a 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.AppService/WorkFlowCores/WorkFlowAppService.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.AppService/WorkFlowCores/WorkFlowAppService.cs @@ -1,4 +1,5 @@ using Common.IBaseRepositories; +using MapsterMapper; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; @@ -22,11 +23,14 @@ namespace WorkFlowCore.AppService.WorkFlows private WorkflowManager workflowManager; private WorkTaskManager workTaskManager; private readonly WorkflowInterface workflowInterface; + private readonly Mapper mapper; private IBasicRepository workflowRepository; private IBasicRepository worktaskRepository; private IBasicRepository versionRepository; private IBasicRepository workStepRepository; private readonly IWorkflowSession workflowSession; + private readonly IWorkTaskRepository workTaskRepository; + public WorkFlowAppService( ConditionManager conditionManager @@ -38,7 +42,8 @@ namespace WorkFlowCore.AppService.WorkFlows , IWorkflowSession workflowSession , WorkTaskManager workTaskManager , WorkflowInterface workflowInterface - ) + , Mapper mapper + ,IWorkTaskRepository workTaskRepository) { this.conditionManager = conditionManager; this.workflowManager = workflowManager; @@ -49,6 +54,8 @@ namespace WorkFlowCore.AppService.WorkFlows this.workflowSession = workflowSession; this.workTaskManager = workTaskManager; this.workflowInterface = workflowInterface; + this.mapper = mapper; + this.workTaskRepository = workTaskRepository; } /// /// 获取所有条件 @@ -187,18 +194,6 @@ namespace WorkFlowCore.AppService.WorkFlows return worktask; } - /// - /// 创建并发起流程任务 - /// - /// - /// - public async Task CreateAndStartWorkTask(CreateWorkTaskInput input) - { - var worktask = await workTaskManager.CreateWorkTask(input.WorkflowId, input.Name, input.FormData, input.EntityFullName, input.EntityKeyValue, input.CreatedUserId); - //await workTaskManager.WorkTaskStart(worktask.Id); - return worktask; - } - /// /// 获取流程任务 /// @@ -218,7 +213,7 @@ namespace WorkFlowCore.AppService.WorkFlows /// public async Task> StartWorkTask(StartWorkTaskInput input) { - var steps = await workTaskManager.WorkTaskStart(input.WorktaskId); + var steps = await workTaskManager.WorkTaskStart(input.WorktaskId, input.FormData); return steps; } /// @@ -304,22 +299,49 @@ namespace WorkFlowCore.AppService.WorkFlows //} + private async Task FillWorktaskInfo(List workTasks) + { + var workflows = await workflowRepository.GetListAsync(w => workTasks.Select(s => s.WorkflowId.Id).Contains(w.Id)); + workTasks.ForEach(i => + { + i.WorkflowId.WorkflowName = workflows.FirstOrDefault(w => w.Id == i.WorkflowId.Id && w.ActiveVersion == i.WorkflowId.VersionId)?.Name; + }); + } + /// /// 获取用户待处理的流程 /// /// - public async Task> GetUnHandledWorkTasksOfUser([FromQuery] GetUnHandledWorkTasksOfUserInput input) + public async Task> GetUnHandledWorkTasksOfUser([FromQuery] GetUnHandledWorkTasksOfUserInput input) { - return await workTaskManager.GetUnHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount); + var worktasks = await workTaskManager.GetUnHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount); + var result = new PageResult + { + Items = mapper.Map, List>(worktasks.Items), + Total = worktasks.Total + }; + await FillWorktaskInfo(result.Items); + + return result; + } /// /// 获取用户已处理的流程 /// /// - public async Task> GetHandledWorkTasksOfUser([FromQuery] GetUnHandledWorkTasksOfUserInput input) + public async Task> GetHandledWorkTasksOfUser([FromQuery] GetHandledWorkTasksOfUserInput input) { - return await workTaskManager.GetHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount); + var worktasks = await workTaskManager.GetHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount); + var result = new PageResult + { + Items = mapper.Map, List>(worktasks.Items), + Total = worktasks.Total + }; + + await FillWorktaskInfo(result.Items); + + return result; } /// /// 根据实体类型获取所有的处理中的工作流 @@ -331,5 +353,42 @@ namespace WorkFlowCore.AppService.WorkFlows var worktaskInfos = await worktaskRepository.GetListAsync(wt => input.EntityKeyValues.Contains(wt.EntityKeyValue) && !wt.Deleted&&wt.EntityFullName== input.EntityFullName); return worktaskInfos.Select(wt=>wt.ToWorkTask()).ToList(); } + + public async Task> GetWorkTasksOfCreator([FromQuery] GetWorkTasksOfCreatorInput input) + { + var worktasks = await workTaskRepository.GetWorkTasksOfCreatorAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount); + var result = new PageResult + { + Items = mapper.Map, List>(worktasks.Items), + Total = worktasks.Total + }; + + await FillWorktaskInfo(result.Items); + + return result; + } + + public async Task> GetAllWorkTasks([FromQuery] GetAllWorkTasksInput input) + { + var worktasks = await workTaskRepository.GetAllWorkTasksAsync( input.CurrentPage, input.MaxResultCount); + var result = new PageResult + { + Items = mapper.Map, List>(worktasks.Items), + Total = worktasks.Total + }; + + await FillWorktaskInfo(result.Items); + + return result; + } + + public async Task DeleteWorkTasks(Guid[] ids) + { + foreach (var id in ids) + { + await workTaskManager.DeleteWorkTask(id); + } + + } } } diff --git a/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories/WorkTaskRepository.cs b/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories/WorkTaskRepository.cs index aa7cc8c0875b91611ccd79dacf9bddadf7eb7a48..799b6bca0d1a0adfbe67ba19cfd5339421ce3eca 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories/WorkTaskRepository.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories/WorkTaskRepository.cs @@ -34,6 +34,42 @@ namespace WorkFlowCore.Framework.Repositories return await Task.FromResult(result); } + public async Task> GetAllWorkTasksAsync(int pageIndex = 1, int pageSize = -1) + { + var workTaskIds = (await workStepRepository.GetListAsync(null)).Select(ws => ws.WorkTaskId); + + var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime); + + var result = new PageResult + { + Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation) + }; + + if (pageSize < 1) + result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList(); + else result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList(); + + return await Task.FromResult(result); + } + + public async Task> GetWorkTasksOfCreatorAsync(string userId, int pageIndex = 1, int pageSize = -1) + { + var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.CreatedUserId == userId && ws.IsHandled)).Select(ws => ws.WorkTaskId); + + var workTasks = (await GetListAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation)).OrderByDescending(ws => ws.CreationTime); + + var result = new PageResult + { + Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation) + }; + + if (pageSize < 1) + result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()))).ToList(); + else result.Items = (await Task.FromResult(workTasks.Select(w => w.ToWorkTask()).Skip((pageIndex - 1) * pageSize).Take(pageSize))).ToList(); + + return await Task.FromResult(result); + } + public async Task> GetHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1) { var workTaskIds = (await workStepRepository.GetListAsync(ws => ws.HandleUser_Id == userId && ws.IsHandled)).Select(ws => ws.WorkTaskId); diff --git a/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories4EF/WorkTaskRepository4EF.cs b/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories4EF/WorkTaskRepository4EF.cs index 27ea12318971a2dac88020ae6b34fa92e21fb0db..8aee1938fe011eac46e03d798b5968be088b22b5 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories4EF/WorkTaskRepository4EF.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.Framework/Repositories4EF/WorkTaskRepository4EF.cs @@ -2,6 +2,8 @@ using Common.BaseRepositories4EF; using Common.IBaseRepositories; using Common.UnitOfWork; +using Common.UnitOfWork4EntityFramework; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -15,12 +17,12 @@ namespace WorkFlowCore.Framework.Repositories4EF { public class WorkTaskRepository4EF : BasicRepository4EF, IWorkTaskRepository { - private readonly WorkflowDbContext workflowDbContext; + private readonly DbContext workflowDbContext; private readonly IWorkStepRepository workStepRepository; public WorkTaskRepository4EF(WorkflowDbContext workflowDbContext, IUnitOfWork unitOfWork, IWorkStepRepository workStepRepository, ICommonSession session) : base(unitOfWork, session) { - this.workflowDbContext = workflowDbContext; + this.workflowDbContext = ((UnitOfWork4EF)unitOfWork).dbContext; this.workStepRepository = workStepRepository; } @@ -41,6 +43,19 @@ namespace WorkFlowCore.Framework.Repositories4EF return await Task.FromResult(result); } + public async Task> GetAllWorkTasksAsync(int pageIndex = 1, int pageSize = -1) + { + var worktaskQuery = workflowDbContext.Set().Where(wt => !wt.Deleted); + var result = new PageResult + { + Total = worktaskQuery.Count() + }; + if (pageSize < 1) + result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList(); + else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(w => w.CreationTime).Select(w => w.ToWorkTask()).ToList(); + return await Task.FromResult(result); + } + public async Task> GetHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1) { var workTaskIds = workflowDbContext.Set().Where(ws => ws.HandleUser_Id == userId && ws.IsHandled).Select(ws => ws.WorkTaskId); @@ -76,7 +91,7 @@ namespace WorkFlowCore.Framework.Repositories4EF { var workTaskIds = workflowDbContext.Set().Where(ws => ws.HandleUser_Id == userId && !ws.IsHandled).Select(ws => ws.WorkTaskId); - var worktaskQuery = workflowDbContext.Set().Where(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation).OrderByDescending(w => w.CreationTime); + var worktaskQuery = workflowDbContext.Set().Where(wt =>wt.WorkTaskStatus== WorkTaskStatus.Processing&& workTaskIds.Contains(wt.Id) && !wt.IsSimulation).OrderByDescending(w => w.CreationTime); var result = new PageResult { @@ -105,5 +120,18 @@ namespace WorkFlowCore.Framework.Repositories4EF else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(w => w.CreationTime).Select(w => w.ToWorkTask()).ToList(); return await Task.FromResult(result); } + + public async Task> GetWorkTasksOfCreatorAsync(string userId, int pageIndex = 1, int pageSize = -1) + { + var worktaskQuery = workflowDbContext.Set().Where(wt => !wt.Deleted && wt.CreatedUserId == userId); + var result = new PageResult + { + Total = worktaskQuery.Count() + }; + if (pageSize < 1) + result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList(); + else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(w => w.CreationTime).Select(w => w.ToWorkTask()).ToList(); + return await Task.FromResult(result); + } } } diff --git a/WorkFlowCore/Workflow/WorkFlowCore.Host/Startup.cs b/WorkFlowCore/Workflow/WorkFlowCore.Host/Startup.cs index ebbf4e5c552848a8fcfdb003cf46b01d09f53818..b076886b8d7f80fa66ccff5fbb10c5d7f8b69bb5 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.Host/Startup.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.Host/Startup.cs @@ -1,4 +1,5 @@ using Common.BackgroundWorker; +using Common.DependencyInjection; using Common.DynamicApi; using Common.EventBus; using Common.EventBus.Kafka; @@ -57,15 +58,14 @@ namespace WorkFlowCore.Host options.DbConnectionString = Configuration.GetValueFromManyChanels("ConnectionStrings:Default"); options.OrmType = WorkFlowCoreFrameworkModule.FrameworkConfigOrmType.EF; }); - - //ע��swagger + services.AddSwaggerGen(c => { - c.SwaggerDoc("v1.0", new OpenApiInfo { Title = "���̷���", Version = "1.0" }); - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name.Split('.')[0]+".AppService"}.xml"; + c.SwaggerDoc("v1", new OpenApiInfo { Title = "WorkFlowCore.Host", Version = "v1" }); + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name.Split('.')[0] + ".AppService"}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - if(File.Exists(xmlPath))c.IncludeXmlComments(xmlPath); + if (File.Exists(xmlPath)) c.IncludeXmlComments(xmlPath); }); // Configure CORS for angular2 UI @@ -94,6 +94,8 @@ namespace WorkFlowCore.Host if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); + app.UseSwagger(); + app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "流程管理V.Host v1")); } else { @@ -107,12 +109,6 @@ namespace WorkFlowCore.Host app.UseAuthorization(); - app.UseSwagger(); - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint("/swagger/v1.0/swagger.json", "���̷���(V 1.0)"); - c.RoutePrefix = string.Empty; - }); app.UseEventBus(); app.RunKafkaEventBus(); app.UseWebApiExceptionHandler(); @@ -127,8 +123,7 @@ namespace WorkFlowCore.Host pattern: "api/{controller=Home}/{action=Index}/{id?}"); }); - //ע��consul - //ע��consul + //注册consul app.RunConsulRegister(options => { options.ConsulAddress = Configuration.GetValueFromManyChanels("Consul:Address"); @@ -136,10 +131,13 @@ namespace WorkFlowCore.Host options.ServiceIP = Configuration.GetValueFromManyChanels("Service:IP"); options.ServicePort = Configuration.GetValueFromManyChanels("Service:Port"); - options.ServiceName = Configuration.GetValueFromManyChanels("Service:Name"); + options.ServiceName = Configuration.GetValueFromManyChanels("Service:Name"); }, hostApplicationLifetime); - //������̨�������� + + //开启后台工作任务 app.RunBackgroundWorker(); + + GlobalServiceProvider.Init(app.ApplicationServices); } diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlowCore.IAppService.csproj b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlowCore.IAppService.csproj index 42b0b969cb88916be3ddf168bc5e52b044d8d3ab..25bfe2dd1cc84538efa615eafcbcc790aa24c670 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlowCore.IAppService.csproj +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlowCore.IAppService.csproj @@ -5,6 +5,7 @@ + diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetAllWorkTasksInput.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetAllWorkTasksInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..ea3b71089227a06116a813217af733e66857179a --- /dev/null +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetAllWorkTasksInput.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WorkFlowCore.IAppService.WorkFlows.Dto +{ + public class GetAllWorkTasksInput + { + public int CurrentPage { get; set; } = 1; + public int MaxResultCount { get; set; } = -1; + } + +} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetHandledWorkTasksOfUserInput.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetHandledWorkTasksOfUserInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..c14bb2ae0ca25d85e52f4e5e484eb54cb99930fb --- /dev/null +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetHandledWorkTasksOfUserInput.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WorkFlowCore.IAppService.WorkFlows.Dto +{ + public class GetHandledWorkTasksOfUserInput + { + public int CurrentPage { get; set; } = 1; + public int MaxResultCount { get; set; } = -1; + } + +} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetWorkTasksOfCreatorInput.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetWorkTasksOfCreatorInput.cs new file mode 100644 index 0000000000000000000000000000000000000000..73548871dc8784b4ca526d571c50de47f01e71cf --- /dev/null +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/GetWorkTasksOfCreatorInput.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace WorkFlowCore.IAppService.WorkFlows.Dto +{ + public class GetWorkTasksOfCreatorInput + { + public int CurrentPage { get; set; } = 1; + public int MaxResultCount { get; set; } = -1; + } + +} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/StartWorkTaskInput.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/StartWorkTaskInput.cs index 7f4a1514c9cacb6593b1ecdc8bfeedee86325810..596feaba6fb2da64bd0ea2cf2f78f95523b61b1c 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/StartWorkTaskInput.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/StartWorkTaskInput.cs @@ -8,5 +8,6 @@ namespace WorkFlowCore.IAppService.WorkFlows.Dto public class StartWorkTaskInput { public Guid WorktaskId { get; set; } + public string FormData { get; set; } } } diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkTaskDto.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkTaskDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..061fd6df4c827176515b9ca4297932b7eb1dffec --- /dev/null +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkTaskDto.cs @@ -0,0 +1,45 @@ +using Common.AppService.Dtos; +using Common.Mapster; +using System; +using System.Collections.Generic; +using System.Text; +using WorkFlowCore.Workflows; +using WorkFlowCore.WorkTasks; + +namespace WorkFlowCore.IAppService.WorkFlows.Dto +{ + [MapFrom(typeof(WorkTask))] + public class WorkTaskDto: BaseModificationDto + { + /// + /// 流程id + /// + public WorkflowIdDto WorkflowId { get; set; } + /// + /// 任务名称 + /// + public string Name { get; set; } + + /// + /// 表单数据(json) + /// + public string FormData { get; set; } + /// + /// 实体全称 + /// + public string EntityFullName { get; set; } + /// + /// 实体主键值 + /// + public string EntityKeyValue { get; set; } + /// + /// 审批状态 + /// + public WorkTaskStatus WorkTaskStatus { get; set; } = WorkTaskStatus.Pending; + + public bool IsProcessed { get => WorkTaskStatus == WorkTaskStatus.Processed; } + public bool IsPending { get => WorkTaskStatus == WorkTaskStatus.Pending; } + public bool IsProcessing { get => WorkTaskStatus == WorkTaskStatus.Processing; } + public bool IsSimulation { get; set; } + } +} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkflowIdDto.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkflowIdDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..263440c345f7842ec00b831ce6e75aa1851a8388 --- /dev/null +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/Dto/WorkflowIdDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkFlowCore.Workflows; + +namespace WorkFlowCore.IAppService.WorkFlows.Dto +{ + public class WorkflowIdDto: WorkflowId + { + /// + /// 流程名称 + /// + public string WorkflowName { get; set; } + } +} diff --git a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/IWorkFlowAppService.cs b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/IWorkFlowAppService.cs index 5d026c075ed3920ac76eee53b7031fa6f9fa4c69..686586a209ba3995d83057a7ca194b3d05054c17 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/IWorkFlowAppService.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.IAppService/WorkFlows/IWorkFlowAppService.cs @@ -26,7 +26,6 @@ namespace WorkFlowCore.IAppService.WorkFlows Task UpdateWorkFlow(UpdateWorkFlowInput input); Task CreateWorkTask(CreateWorkTaskInput input); Task CreateSimulationWorkTask(CreateWorkTaskInput input); - Task CreateAndStartWorkTask(CreateWorkTaskInput input); Task GetWorkTask(Guid id); Task> StartWorkTask(StartWorkTaskInput input); Task> PassProve(ProveInput input); @@ -35,8 +34,11 @@ namespace WorkFlowCore.IAppService.WorkFlows Task> ForwardProve(ForwardProveInput input); Task> GetAllTaskStepsOfWorkTask(Guid? worktaskId); Task> GetAllTaskStepsOfWorkTaskByEntityInfo(string entityFullName, string entityKeyValue); - Task> GetUnHandledWorkTasksOfUser(GetUnHandledWorkTasksOfUserInput input); - Task> GetHandledWorkTasksOfUser( GetUnHandledWorkTasksOfUserInput input); + Task> GetUnHandledWorkTasksOfUser(GetUnHandledWorkTasksOfUserInput input); + Task> GetHandledWorkTasksOfUser(GetHandledWorkTasksOfUserInput input); Task> GetAllProcessingWorkTasksByEntityType(GetAllProcessingWorkTasksByEntityTypeInput input); + Task> GetWorkTasksOfCreator(GetWorkTasksOfCreatorInput input); + Task> GetAllWorkTasks(GetAllWorkTasksInput input); + Task DeleteWorkTasks(Guid[] ids); } } diff --git a/WorkFlowCore/Workflow/WorkFlowCore.Test/Workflow/Workflow_Test.cs b/WorkFlowCore/Workflow/WorkFlowCore.Test/Workflow/Workflow_Test.cs index 694b5173dda5de91d52d3803db60a041e5195720..cb7b0d976d6285524acd9ce738a75458ae02470f 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore.Test/Workflow/Workflow_Test.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore.Test/Workflow/Workflow_Test.cs @@ -156,9 +156,10 @@ namespace WorkFlowCore.Test.Workflow var wf = workflowManager.GetWorkflowByNo("wfno").Result; WorkflowId workflowId = new WorkflowId(wf.ActiveVersion, wf.Id); - var worktask = workTaskManager.CreateWorkTask ( workflowId, "测试流程", JsonConvert.SerializeObject(new { x = 2, y = 1 }), "", "","").Result; + var formData = JsonConvert.SerializeObject(new { x = 2, y = 1 }); + var worktask = workTaskManager.CreateWorkTask ( workflowId, "测试流程", formData, "", "","").Result; - var steps = workTaskManager.WorkTaskStart(worktask.Id).Result; + var steps = workTaskManager.WorkTaskStart(worktask.Id, formData).Result; List fxSteps = steps; diff --git a/WorkFlowCore/Workflow/WorkFlowCore/IRepositories/IWorkTaskRepository.cs b/WorkFlowCore/Workflow/WorkFlowCore/IRepositories/IWorkTaskRepository.cs index f3374c18a79edf26617a10ca8f4adeef13306a9a..fbb1937b5d220a489871a5017b3669a21b5abc50 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore/IRepositories/IWorkTaskRepository.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore/IRepositories/IWorkTaskRepository.cs @@ -14,5 +14,7 @@ namespace WorkFlowCore.IRepositories Task> GetUnHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1); Task> GetHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1); Task> GetTasksOfStartUserAsync(string userId, int pageIndex = 1, int pageSize = -1); + Task> GetAllWorkTasksAsync(int pageIndex = 1, int pageSize = -1); + Task> GetWorkTasksOfCreatorAsync(string userId, int pageIndex = 1, int pageSize = -1); } } diff --git a/WorkFlowCore/Workflow/WorkFlowCore/WorkTasks/WorkTaskManager.cs b/WorkFlowCore/Workflow/WorkFlowCore/WorkTasks/WorkTaskManager.cs index c76bdce7d77eb2a044aafcb14467f8dc9b35274b..4666e221a9610d19f2ea65cb20330cfbc88503c1 100644 --- a/WorkFlowCore/Workflow/WorkFlowCore/WorkTasks/WorkTaskManager.cs +++ b/WorkFlowCore/Workflow/WorkFlowCore/WorkTasks/WorkTaskManager.cs @@ -256,12 +256,17 @@ namespace WorkFlowCore.WorkTasks /// /// /// - public async Task> WorkTaskStart(Guid workTaskId) + public async Task> WorkTaskStart(Guid workTaskId,string formData) { var workTaskInfo = await workTaskRepository.GetAsync(workTaskId); if (workTaskInfo == null) return new List(); var workTask = workTaskInfo.ToWorkTask(); if (!workTask.IsPending) return new List(); + + await workStepRepository.DeleteManyAsync(ws => ws.WorkTaskId == workTaskId); + + if (!string.IsNullOrEmpty(formData)) + workTask.FormData = formData; workTask.SetProcessing(); var workflowVersion = await workflowInterface.GetWorkflowVersion(workTask.WorkflowId.Id, workTask.WorkflowId.VersionId); var startNode = workflowVersion?.NodeMaps?.FirstOrDefault(n => n.FromNode.NodeType == WorkNodeType.Begin)?.FromNode; @@ -912,10 +917,22 @@ namespace WorkFlowCore.WorkTasks /// public async Task DeleteWorkTask(Guid worktaskId) { + var worktaskInfo = await workTaskRepository.GetAsync(worktaskId); + + if (worktaskInfo == null) + throw new Exception($"查无此项:{worktaskId}"); + + var worktask = worktaskInfo.ToWorkTask(); + + if(!worktask.IsPending) + throw new Exception("非待审批状态无法删除"); + await workStepRepository.DeleteManyAsync(ws => ws.WorkTaskId == worktaskId); await workTaskRepository.DeleteAsync(worktaskId); } #endregion + + } } diff --git a/admin/vue-admin-template/src/store/modules/dynamicFormInstance.js b/admin/vue-admin-template/src/store/modules/dynamicFormInstance.js index c9a6f9462334c64565dd741ca997dab5171863ac..3dde7977dc87806cbd12082c35d79d44cfe7adcc 100644 --- a/admin/vue-admin-template/src/store/modules/dynamicFormInstance.js +++ b/admin/vue-admin-template/src/store/modules/dynamicFormInstance.js @@ -109,14 +109,14 @@ const actions = { params: params }) }, - createAndStartWorkTask({ + startWorkTask({ commit, state - }, params) { + }, data) { return request({ - url: '/dynamicForm/api/FormInstance/createAndStartWorkTask', + url: '/dynamicForm/api/FormInstance/startWorkTask', method: 'post', - params: params + data: data }) } diff --git a/admin/vue-admin-template/src/store/modules/organisationOrg.js b/admin/vue-admin-template/src/store/modules/organisationOrg.js index 9a6982b54f73955ecf230d54b5946697a62250b2..8688836440c8763abdf92011e71c6d9b8ae12920 100644 --- a/admin/vue-admin-template/src/store/modules/organisationOrg.js +++ b/admin/vue-admin-template/src/store/modules/organisationOrg.js @@ -94,7 +94,7 @@ const actions = { }, data) { return request({ url: '/organisation/api/Organization/SetOrganizationLeaders', - method: 'post', + method: 'put', data: data }) }, diff --git a/admin/vue-admin-template/src/store/modules/workflow.js b/admin/vue-admin-template/src/store/modules/workflow.js index 09eb783d7974616a6fed34ca86d3fca186445312..1855db052ddb068260e40d33f790b3cc79333f7a 100644 --- a/admin/vue-admin-template/src/store/modules/workflow.js +++ b/admin/vue-admin-template/src/store/modules/workflow.js @@ -299,8 +299,37 @@ const actions = { }) }, - + getWorkTasksOfCreator({ + commit, + state + }, params) { + return request({ + url: '/workflow/api/WorkFlow/GetWorkTasksOfCreator', + method: 'get', + params: params + }) + }, + getAllWorkTasks({ + commit, + state + }, params) { + return request({ + url: '/workflow/api/WorkFlow/GetAllWorkTasks', + method: 'get', + params: params + }) + }, + deleteWorkTasks({ + commit, + state + }, data) { + return request({ + url: '/workflow/api/WorkFlow/deleteWorkTasks', + method: 'delete', + data: data + }) + }, } export default { diff --git a/admin/vue-admin-template/src/views/workflows/formDesign/components/dynamicCol.vue b/admin/vue-admin-template/src/views/workflows/formDesign/components/dynamicCol.vue index 109b9594b36976f3cbbf285b623858aded81be31..3fca0d776362dcc6f8d25f2f06694f581f38f6b2 100644 --- a/admin/vue-admin-template/src/views/workflows/formDesign/components/dynamicCol.vue +++ b/admin/vue-admin-template/src/views/workflows/formDesign/components/dynamicCol.vue @@ -32,6 +32,7 @@ @@ -52,18 +53,20 @@ placement="top" > - + + 编辑 - + + 复制 @@ -74,7 +77,8 @@ placement="top" > - + + 删除 diff --git a/admin/vue-admin-template/src/views/workflows/formInstance/index.vue b/admin/vue-admin-template/src/views/workflows/formInstance/index.vue index a115eb0f3dbf05bec14c0c5634149f109d452227..b81e1240e9b59b7bcd034e1549bfee544cf88798 100644 --- a/admin/vue-admin-template/src/views/workflows/formInstance/index.vue +++ b/admin/vue-admin-template/src/views/workflows/formInstance/index.vue @@ -8,14 +8,19 @@ - - + + + + 查看 查看流程 { + this.tableData = res.items; + this.page.total = res.total; + this.loading.getPageList = false + }); + }, getDesignName(designId) { var designs = this.selections.filter((s) => s.id == designId); return designs && designs.length > 0 ? designs[0].title : ""; diff --git a/admin/vue-admin-template/src/views/workflows/formInstance/viewForm.vue b/admin/vue-admin-template/src/views/workflows/formInstance/viewForm.vue index f9023cb2ffdf5c2d613725299c107876753c85bd..27d4bb935c06e24a9a85d60d8d5a19e27c8b81d6 100644 --- a/admin/vue-admin-template/src/views/workflows/formInstance/viewForm.vue +++ b/admin/vue-admin-template/src/views/workflows/formInstance/viewForm.vue @@ -1,7 +1,7 @@