feat: 合并
This commit is contained in:
@@ -107,13 +107,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManageme
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code-gen", "code-gen", "{4FFE7212-21F2-476D-B628-3C65E6C5075E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code-gen", "code-gen", "{4FFE7212-21F2-476D-B628-3C65E6C5075E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application", "module\code-gen\Yi.Framework.Codegen.Application\Yi.Framework.CodeGen.Application.csproj", "{97EC40D7-DBFA-467A-98CB-221AF27B14F2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application", "module\code-gen\Yi.Framework.CodeGen.Application\Yi.Framework.CodeGen.Application.csproj", "{97EC40D7-DBFA-467A-98CB-221AF27B14F2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application.Contracts", "module\code-gen\Yi.Framework.Codegen.Application.Contracts\Yi.Framework.CodeGen.Application.Contracts.csproj", "{882BC563-2F75-4B95-AC96-F4BF23F5E69D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application.Contracts", "module\code-gen\Yi.Framework.CodeGen.Application.Contracts\Yi.Framework.CodeGen.Application.Contracts.csproj", "{882BC563-2F75-4B95-AC96-F4BF23F5E69D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain", "module\code-gen\Yi.Framework.Codegen.Domain\Yi.Framework.CodeGen.Domain.csproj", "{85CB8517-2B80-42D8-B954-081079AC9BA0}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain", "module\code-gen\Yi.Framework.CodeGen.Domain\Yi.Framework.CodeGen.Domain.csproj", "{85CB8517-2B80-42D8-B954-081079AC9BA0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain.Shared", "module\code-gen\Yi.Framework.Codegen.Domain.Shared\Yi.Framework.CodeGen.Domain.Shared.csproj", "{EEFF0F05-2709-4151-A8CE-667935CEAE0B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain.Shared", "module\code-gen\Yi.Framework.CodeGen.Domain.Shared\Yi.Framework.CodeGen.Domain.Shared.csproj", "{EEFF0F05-2709-4151-A8CE-667935CEAE0B}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.FreeRedis", "framework\Yi.Framework.Caching.FreeRedis\Yi.Framework.Caching.FreeRedis.csproj", "{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.CodeGen.SqlSugarCore", "module\code-gen\Yi.Framework.CodeGen.SqlSugarCore\Yi.Framework.CodeGen.SqlSugarCore.csproj", "{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -289,6 +293,14 @@ Global
|
|||||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -341,6 +353,8 @@ Global
|
|||||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
{882BC563-2F75-4B95-AC96-F4BF23F5E69D} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||||
{85CB8517-2B80-42D8-B954-081079AC9BA0} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
{85CB8517-2B80-42D8-B954-081079AC9BA0} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
{EEFF0F05-2709-4151-A8CE-667935CEAE0B} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||||
|
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||||
|
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}
|
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FreeRedis;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Caching.FreeRedis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 便于转到定义
|
||||||
|
/// </summary>
|
||||||
|
public class FreeSqlOptions: ConnectionStringBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="..\..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FreeRedis" Version="1.2.13" />
|
||||||
|
<PackageReference Include="FreeRedis.DistributedCache" Version="1.2.5" />
|
||||||
|
<PackageReference Include="Volo.Abp.Caching" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Caching.FreeRedis
|
||||||
|
{
|
||||||
|
[Dependency(ReplaceServices =true)]
|
||||||
|
public class YiDistributedCacheKeyNormalizer : IDistributedCacheKeyNormalizer, ITransientDependency
|
||||||
|
{
|
||||||
|
protected ICurrentTenant CurrentTenant { get; }
|
||||||
|
|
||||||
|
protected AbpDistributedCacheOptions DistributedCacheOptions { get; }
|
||||||
|
|
||||||
|
public YiDistributedCacheKeyNormalizer(
|
||||||
|
ICurrentTenant currentTenant,
|
||||||
|
IOptions<AbpDistributedCacheOptions> distributedCacheOptions)
|
||||||
|
{
|
||||||
|
CurrentTenant = currentTenant;
|
||||||
|
DistributedCacheOptions = distributedCacheOptions.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string NormalizeKey(DistributedCacheKeyNormalizeArgs args)
|
||||||
|
{
|
||||||
|
var normalizedKey = $"{DistributedCacheOptions.KeyPrefix}{args.Key}";
|
||||||
|
|
||||||
|
//if (!args.IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
|
||||||
|
//{
|
||||||
|
// normalizedKey = $"t:{CurrentTenant.Id.Value},{normalizedKey}";
|
||||||
|
//}
|
||||||
|
|
||||||
|
return normalizedKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using FreeRedis;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Caching.FreeRedis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 此模块得益于FreeRedis作者支持IDistributedCache,使用湿滑
|
||||||
|
/// </summary>
|
||||||
|
[DependsOn(typeof(AbpCachingModule))]
|
||||||
|
public class YiFrameworkCachingFreeRedisModule : AbpModule
|
||||||
|
{
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
|
||||||
|
var configuration = context.Services.GetConfiguration();
|
||||||
|
|
||||||
|
var redisEnabled = configuration["Redis:IsEnabled"];
|
||||||
|
if (redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled))
|
||||||
|
{
|
||||||
|
var redisConfiguration = configuration["Redis:Configuration"];
|
||||||
|
RedisClient redisClient = new RedisClient(redisConfiguration);
|
||||||
|
|
||||||
|
context.Services.AddSingleton<IRedisClient>(redisClient);
|
||||||
|
context.Services.Replace(ServiceDescriptor.Singleton<IDistributedCache>(new
|
||||||
|
DistributedCache(redisClient)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,6 +60,7 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
{
|
{
|
||||||
options.ConnectionString = currentConnection;
|
options.ConnectionString = currentConnection;
|
||||||
}));
|
}));
|
||||||
|
connectionCreator.SetDbAop(SqlSugarClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -242,6 +243,11 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
/// <param name="pars"></param>
|
/// <param name="pars"></param>
|
||||||
protected virtual void OnLogExecuted(string sql, SugarParameter[] pars)
|
protected virtual void OnLogExecuted(string sql, SugarParameter[] pars)
|
||||||
{
|
{
|
||||||
|
if (Options.EnabledSqlLog)
|
||||||
|
{
|
||||||
|
var sqllog = $"=========Yi-SQL耗时{SqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds}毫秒=====";
|
||||||
|
Logger.CreateLogger<SqlSugarDbContext>().LogDebug(sqllog.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -251,7 +257,14 @@ namespace Yi.Framework.SqlSugarCore
|
|||||||
/// <param name="column"></param>
|
/// <param name="column"></param>
|
||||||
protected virtual void EntityService(PropertyInfo property, EntityColumnInfo column)
|
protected virtual void EntityService(PropertyInfo property, EntityColumnInfo column)
|
||||||
{
|
{
|
||||||
|
if (property.PropertyType == typeof(ExtraPropertyDictionary))
|
||||||
|
{
|
||||||
|
column.IsIgnore = true;
|
||||||
|
}
|
||||||
|
if (property.Name == nameof(Entity<object>.Id))
|
||||||
|
{
|
||||||
|
column.IsPrimarykey = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BackupDataBase()
|
public void BackupDataBase()
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.EventBus.Local;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Integral;
|
using Yi.Framework.Bbs.Application.Contracts.Dtos.Integral;
|
||||||
using Yi.Framework.Bbs.Domain.Managers;
|
using Yi.Framework.Bbs.Domain.Managers;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
using Yi.Framework.Rbac.Domain.Authorization;
|
using Yi.Framework.Rbac.Domain.Authorization;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Services.Integral
|
namespace Yi.Framework.Bbs.Application.Services.Integral
|
||||||
@@ -17,10 +19,12 @@ namespace Yi.Framework.Bbs.Application.Services.Integral
|
|||||||
{
|
{
|
||||||
private IntegralManager _integralManager;
|
private IntegralManager _integralManager;
|
||||||
private ICurrentUser _currentUser;
|
private ICurrentUser _currentUser;
|
||||||
public IntegralService(IntegralManager integralManager, ICurrentUser currentUser)
|
private ILocalEventBus _localEventBus;
|
||||||
|
public IntegralService(IntegralManager integralManager, ICurrentUser currentUser, ILocalEventBus localEventBus)
|
||||||
{
|
{
|
||||||
_integralManager = integralManager;
|
_integralManager = integralManager;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
|
_localEventBus = localEventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Yi.Framework.Bbs.Domain.Shared.Consts
|
|||||||
{
|
{
|
||||||
public class LevelConst
|
public class LevelConst
|
||||||
{
|
{
|
||||||
public const string LevelCacheKey=nameof(LevelCacheKey);
|
public const string LevelCacheKey="Level:All";
|
||||||
|
|
||||||
public const string Level_Low_Zero = "经验提升等级低于或等于0";
|
public const string Level_Low_Zero = "经验提升等级低于或等于0";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace Yi.Framework.CodeGen.Domain.Shared.Enums
|
|||||||
|
|
||||||
[Display(Name = "DateTime", Description = "DateTime")]
|
[Display(Name = "DateTime", Description = "DateTime")]
|
||||||
DateTime,
|
DateTime,
|
||||||
|
|
||||||
|
[Display(Name = "Guid", Description = "Guid")]
|
||||||
|
Guid
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
using Volo.Abp.Data;
|
||||||
using Volo.Abp.Domain.Entities;
|
using Volo.Abp.Domain.Entities;
|
||||||
|
|
||||||
namespace Yi.Framework.CodeGen.Domain.Entities
|
namespace Yi.Framework.CodeGen.Domain.Entities
|
||||||
@@ -24,5 +25,8 @@ namespace Yi.Framework.CodeGen.Domain.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Navigate(NavigateType.OneToMany, nameof(FieldEntity.TableId))]
|
[Navigate(NavigateType.OneToMany, nameof(FieldEntity.TableId))]
|
||||||
public List<FieldEntity> Fields { get; set; }
|
public List<FieldEntity> Fields { get; set; }
|
||||||
|
|
||||||
|
[SugarColumn(IsIgnore =true)]
|
||||||
|
public override ExtraPropertyDictionary ExtraProperties { get; protected set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Guids;
|
||||||
|
using Yi.Framework.CodeGen.Domain.Entities;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
|
namespace Yi.Framework.CodeGen.SqlSugarCore
|
||||||
|
{
|
||||||
|
public class TemplateDataSeed : IDataSeedContributor, ITransientDependency
|
||||||
|
{
|
||||||
|
private ISqlSugarRepository<TemplateEntity> _repository;
|
||||||
|
public TemplateDataSeed(ISqlSugarRepository<TemplateEntity> repository)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
public async Task SeedAsync(DataSeedContext context)
|
||||||
|
{
|
||||||
|
if (!await _repository.IsAnyAsync(x => true))
|
||||||
|
{
|
||||||
|
await _repository.InsertManyAsync(GetSeedData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<TemplateEntity> GetSeedData()
|
||||||
|
{
|
||||||
|
var entities = new List<TemplateEntity>();
|
||||||
|
TemplateEntity entityTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "Entity",
|
||||||
|
BuildPath = "D:\\code\\Entities\\@ModelEntity.cs",
|
||||||
|
Remarks = "实体",
|
||||||
|
TemplateStr = "using SqlSugar;\r\nusing lo.Abp;\r\nusing lo.Abp.Auditing;\r\nusing lo.Abp.Domain.Entities;\r\nusing Yi.Framework.Core.Data;\r\n\r\nnamespace Yi.Framework.Rbac.Domain.Entities\r\n{\r\n /// <summary>\r\n /// 实体\r\n /// </summary>\r\n [SugarTable(\"@Model\")]\r\n public class @ModelEntity : Entity<Guid>\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(entityTemplate);
|
||||||
|
|
||||||
|
|
||||||
|
TemplateEntity getListInputTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "GetListInput",
|
||||||
|
BuildPath = "D:\\code\\Dtos\\@Model\\@ModelGetListInput.cs",
|
||||||
|
Remarks = "列表查询参数",
|
||||||
|
TemplateStr = "using Yi.Framework.Ddd;\r\nusing Yi.Framework.Ddd.Application.Contracts;\r\n\r\nnamespace Yi.Framework.Rbac.Application.Contracts.Dtos.@Model\r\n{\r\n /// <summary>\r\n /// 查询参数\r\n /// </summary>\r\n public class @ModelGetListInput : PagedAllResultRequestDto\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(getListInputTemplate);
|
||||||
|
|
||||||
|
|
||||||
|
TemplateEntity getListOutputDtoTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "GetListOutputDto",
|
||||||
|
BuildPath = "D:\\code\\Dtos\\@Model\\@ModelGetListOutputDto.cs",
|
||||||
|
Remarks = "列表返回dto",
|
||||||
|
TemplateStr = "using lo.Abp.Application.Dtos;\r\n\r\nnamespace Yi.Framework.Rbac.Application.Contracts.Dtos.@Model\r\n{\r\n public class @ModelGetListOutputDto : EntityDto<Guid>\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(getListOutputDtoTemplate);
|
||||||
|
|
||||||
|
|
||||||
|
TemplateEntity getOutputDtoTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "GetOutputDto",
|
||||||
|
BuildPath = "D:\\code\\Dtos\\@Model\\@ModelGetOutputDto.cs",
|
||||||
|
Remarks = "单返回dto",
|
||||||
|
TemplateStr = "using lo.Abp.Application.Dtos;\r\n\r\nnamespace Yi.Framework.Rbac.Application.Contracts.Dtos.@Model\r\n{\r\n public class @ModelGetOutputDto : EntityDto<Guid>\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(getOutputDtoTemplate);
|
||||||
|
|
||||||
|
TemplateEntity updateInputTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "UpdateInput",
|
||||||
|
BuildPath = "D:\\code\\Dtos\\@Model\\@ModelUpdateInput.cs",
|
||||||
|
Remarks = "更新输入",
|
||||||
|
TemplateStr = "namespace Yi.Framework.Rbac.Application.Contracts.Dtos.@Model\r\n{\r\n public class @ModelUpdateInput\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(updateInputTemplate);
|
||||||
|
|
||||||
|
TemplateEntity createInputTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "CreateInput",
|
||||||
|
BuildPath = "D:\\code\\Dtos\\@Model\\@ModelCreateInput.cs",
|
||||||
|
Remarks = "创建dto",
|
||||||
|
TemplateStr = "namespace Yi.Framework.Rbac.Application.Contracts.Dtos.@Model\r\n{\r\n /// <summary>\r\n /// @Model输入创建对象\r\n /// </summary>\r\n public class @ModelCreateInput\r\n {\r\n@field\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(createInputTemplate);
|
||||||
|
|
||||||
|
|
||||||
|
TemplateEntity iServicesTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "IServices",
|
||||||
|
BuildPath = "D:\\code\\IServices\\I@ModelService.cs",
|
||||||
|
Remarks = "应用服务抽象",
|
||||||
|
TemplateStr = "using lo.Abp.Application.Services;\r\nusing Yi.Framework.Ddd.Application.Contracts;\r\nusing Yi.Framework.Rbac.Application.Contracts.Dtos.@Model;\r\n\r\nnamespace Yi.Framework.Rbac.Application.Contracts.IServices\r\n{\r\n /// <summary>\r\n /// @Model服务抽象\r\n /// </summary>\r\n public interface I@ModelService : IYiCrudAppService<@ModelGetOutputDto, @ModelGetListOutputDto, Guid, @ModelGetListInput, @ModelCreateInput, @ModelUpdateInput>\r\n {\r\n\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(iServicesTemplate);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TemplateEntity servicesTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
Name = "Service",
|
||||||
|
BuildPath = "D:\\code\\Services\\@ModelService.cs",
|
||||||
|
Remarks = "应用服务",
|
||||||
|
TemplateStr = "using SqlSugar;\r\nusing lo.Abp.Application.Dtos;\r\nusing lo.Abp.Application.Services;\r\nusing Yi.Framework.Ddd.Application;\r\nusing Yi.Framework.Rbac.Application.Contracts.Dtos.@Model;\r\nusing Yi.Framework.Rbac.Application.Contracts.IServices;\r\nusing Yi.Framework.Rbac.Domain.Entities;\r\nusing Yi.Framework.SqlSugarCore.Abstractions;\r\n\r\nnamespace Yi.Framework.Rbac.Application.Services\r\n{\r\n /// <summary>\r\n /// @Model服务实现\r\n /// </summary>\r\n public class @ModelService : YiCrudAppService<@ModelEntity, @ModelGetOutputDto, @ModelGetListOutputDto, Guid, @ModelGetListInput, @ModelCreateInput, @ModelUpdateInput>,\r\n I@ModelService\r\n {\r\n private ISqlSugarRepository<@ModelEntity, Guid> _repository;\r\n public @ModelService(ISqlSugarRepository<@ModelEntity, Guid> repository) : base(repository)\r\n {\r\n _repository = repository;\r\n }\r\n\r\n /// <summary>\r\n /// 多查\r\n /// </summary>\r\n /// <param name=\"input\"></param>\r\n /// <returns></returns>\r\n public override async Task<PagedResultDto<@ModelGetListOutputDto>> GetListAsync(@ModelGetListInput input)\r\n {\r\n RefAsync<int> total = 0;\r\n\r\n var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.@ModelKey), x => x.@ModelKey.Contains(input.@ModelKey!))\r\n .WhereIF(!string.IsNullOrEmpty(input.@ModelName), x => x.@ModelName!.Contains(input.@ModelName!))\r\n .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)\r\n .ToPageListAsync(input.SkipCount, input.MaxResultCount, total);\r\n return new PagedResultDto<@ModelGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));\r\n }\r\n }\r\n}\r\n"
|
||||||
|
};
|
||||||
|
entities.Add(servicesTemplate);
|
||||||
|
|
||||||
|
TemplateEntity apiTemplate = new TemplateEntity()
|
||||||
|
{
|
||||||
|
TemplateStr = "import request from '@/utils/request'\r\n\r\n// 分页查询\r\nexport function listData(query) {\r\n return request({\r\n url: '/@model',\r\n method: 'get',\r\n params: query\r\n })\r\n}\r\n\r\n// id查询\r\nexport function getData(id) {\r\n return request({\r\n url: `/@model/${id}`,\r\n method: 'get'\r\n })\r\n}\r\n\r\n// 新增\r\nexport function addData(data) {\r\n return request({\r\n url: '/@model',\r\n method: 'post',\r\n data: data\r\n })\r\n}\r\n\r\n// 修改\r\nexport function updateData(id,data) {\r\n return request({\r\n url: `/@model/${id}`,\r\n method: 'put',\r\n data: data\r\n })\r\n}\r\n\r\n// 删除\r\nexport function delData(ids) {\r\n return request({\r\n url: `/@model`,\r\n method: 'delete',\r\n params:{id:ids}\r\n })\r\n}\r\n",
|
||||||
|
Name = "api",
|
||||||
|
BuildPath = "D:\\code\\Api\\@ModelApi.vue",
|
||||||
|
Remarks = "前端api"
|
||||||
|
};
|
||||||
|
entities.Add(apiTemplate);
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="..\..\..\common.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
|
||||||
|
<ProjectReference Include="..\Yi.Framework.CodeGen.Domain\Yi.Framework.CodeGen.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Yi.Framework.SqlSugarCore;
|
||||||
|
|
||||||
|
namespace Yi.Framework.CodeGen.SqlSugarCore
|
||||||
|
{
|
||||||
|
[DependsOn(typeof(YiFrameworkSqlSugarCoreModule))]
|
||||||
|
public class YiFrameworkCodeGenSqlSugarCoreModule:AbpModule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Notice
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notice输入创建对象
|
||||||
|
/// </summary>
|
||||||
|
public class NoticeCreateInput
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public NoticeTypeEnum Type { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public int OrderNum { get; set; }
|
||||||
|
public bool State { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using Yi.Framework.Ddd.Application.Contracts;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Notice
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 查询参数
|
||||||
|
/// </summary>
|
||||||
|
public class NoticeGetListInput : PagedAllResultRequestDto
|
||||||
|
{
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public NoticeTypeEnum? Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Notice
|
||||||
|
{
|
||||||
|
public class NoticeGetListOutputDto : EntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public NoticeTypeEnum Type { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
public DateTime CreationTime { get; set; }
|
||||||
|
public Guid? CreatorId { get; set; }
|
||||||
|
public Guid? LastModifierId { get; set; }
|
||||||
|
public DateTime? LastModificationTime { get; set; }
|
||||||
|
public int OrderNum { get; set; }
|
||||||
|
public bool State { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Notice
|
||||||
|
{
|
||||||
|
public class NoticeGetOutputDto : EntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public NoticeTypeEnum Type { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
public DateTime CreationTime { get; set; }
|
||||||
|
public Guid? CreatorId { get; set; }
|
||||||
|
public Guid? LastModifierId { get; set; }
|
||||||
|
public DateTime? LastModificationTime { get; set; }
|
||||||
|
public int OrderNum { get; set; }
|
||||||
|
public bool State { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Notice
|
||||||
|
{
|
||||||
|
public class NoticeUpdateInput
|
||||||
|
{
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public NoticeTypeEnum? Type { get; set; }
|
||||||
|
public string? Content { get; set; }
|
||||||
|
public int? OrderNum { get; set; }
|
||||||
|
public bool? State { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Yi.Framework.Ddd.Application.Contracts;
|
||||||
|
using Yi.Framework.Rbac.Application.Contracts.Dtos.Notice;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Contracts.IServices
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notice服务抽象
|
||||||
|
/// </summary>
|
||||||
|
public interface INoticeService : IYiCrudAppService<NoticeGetOutputDto, NoticeGetListOutputDto, Guid, NoticeGetListInput, NoticeCreateInput, NoticeUpdateInput>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Lazy.Captcha.Core;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
@@ -33,15 +34,17 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
private readonly IGuidGenerator _guidGenerator;
|
private readonly IGuidGenerator _guidGenerator;
|
||||||
private readonly RbacOptions _rbacOptions;
|
private readonly RbacOptions _rbacOptions;
|
||||||
private readonly IAliyunManger _aliyunManger;
|
private readonly IAliyunManger _aliyunManger;
|
||||||
|
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
|
||||||
public AccountService(IUserRepository userRepository,
|
public AccountService(IUserRepository userRepository,
|
||||||
ICurrentUser currentUser,
|
ICurrentUser currentUser,
|
||||||
IAccountManager accountManager,
|
IAccountManager accountManager,
|
||||||
ISqlSugarRepository<MenuEntity> menuRepository,
|
ISqlSugarRepository<MenuEntity> menuRepository,
|
||||||
IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> phoneCache,
|
IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> phoneCache,
|
||||||
|
IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> userCache,
|
||||||
ICaptcha captcha,
|
ICaptcha captcha,
|
||||||
IGuidGenerator guidGenerator,
|
IGuidGenerator guidGenerator,
|
||||||
IOptions<RbacOptions> options,
|
IOptions<RbacOptions> options,
|
||||||
IAliyunManger aliyunManger )
|
IAliyunManger aliyunManger)
|
||||||
{
|
{
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
@@ -52,6 +55,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
_guidGenerator = guidGenerator;
|
_guidGenerator = guidGenerator;
|
||||||
_rbacOptions = options.Value;
|
_rbacOptions = options.Value;
|
||||||
_aliyunManger = aliyunManger;
|
_aliyunManger = aliyunManger;
|
||||||
|
_userCache = userCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -113,10 +117,10 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
[Authorize(AuthenticationSchemes = TokenTypeConst.Refresh)]
|
[Authorize(AuthenticationSchemes = TokenTypeConst.Refresh)]
|
||||||
public async Task<object> PostRefreshAsync([FromQuery] string refresh_token)
|
public async Task<object> PostRefreshAsync([FromQuery] string refresh_token)
|
||||||
{
|
{
|
||||||
var userId = CurrentUser.Id.Value;
|
var userId = CurrentUser.Id.Value;
|
||||||
var accessToken = await _accountManager.GetTokenByUserIdAsync(userId);
|
var accessToken = await _accountManager.GetTokenByUserIdAsync(userId);
|
||||||
var refreshToken = _accountManager.CreateRefreshToken(userId);
|
var refreshToken = _accountManager.CreateRefreshToken(userId);
|
||||||
return new { Token = accessToken, RefreshToken = refreshToken };
|
return new { Token = accessToken, RefreshToken = refreshToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -249,7 +253,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询已登录的账户信息
|
/// 查询已登录的账户信息,已缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[Route("account")]
|
[Route("account")]
|
||||||
@@ -263,16 +267,33 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
{
|
{
|
||||||
throw new UserFriendlyException("用户未登录");
|
throw new UserFriendlyException("用户未登录");
|
||||||
}
|
}
|
||||||
//此处从缓存中获取也行
|
//此处优先从缓存中获取
|
||||||
//var data = _cacheManager.Get<UserRoleMenuDto>($"Yi:UserInfo:{userId}");
|
UserRoleMenuDto output = null;
|
||||||
var data = await _userRepository.GetUserAllInfoAsync(userId ?? Guid.Empty);
|
var cacheData = await _userCache.GetAsync(new UserInfoCacheKey(userId.Value));
|
||||||
//系统用户数据被重置,老前端访问重新授权
|
if (cacheData is not null)
|
||||||
if (data is null)
|
|
||||||
{
|
{
|
||||||
throw new AbpAuthorizationException();
|
output = cacheData.Info;
|
||||||
}
|
}
|
||||||
data.Menus.Clear();
|
else
|
||||||
return data;
|
{
|
||||||
|
var data = await _userRepository.GetUserAllInfoAsync(userId.Value);
|
||||||
|
//系统用户数据被重置,老前端访问重新授权
|
||||||
|
if (data is null)
|
||||||
|
{
|
||||||
|
throw new AbpAuthorizationException();
|
||||||
|
}
|
||||||
|
data.Menus.Clear();
|
||||||
|
|
||||||
|
output = data;
|
||||||
|
|
||||||
|
var tokenExpiresMinuteTime = LazyServiceProvider.GetRequiredService<IOptions<JwtOptions>>().Value.ExpiresMinuteTime;
|
||||||
|
//将用户信息放入缓存,下次获取直接从缓存中获取即可,过期时间为token过期时间
|
||||||
|
await _userCache.SetAsync(new UserInfoCacheKey(userId.Value), new UserInfoCacheItem(data), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(tokenExpiresMinuteTime) });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -307,10 +328,18 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// 退出登录
|
/// 退出登录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<bool> PostLogout()
|
public async Task<bool> PostLogout()
|
||||||
{
|
{
|
||||||
|
//通过鉴权jwt获取到用户的id
|
||||||
|
var userId = _currentUser.Id;
|
||||||
|
if (userId is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
// throw new UserFriendlyException("用户已退出");
|
||||||
|
}
|
||||||
|
await _userCache.RemoveAsync(new UserInfoCacheKey(userId.Value));
|
||||||
//Jwt去中心化登出,只需用记录日志即可
|
//Jwt去中心化登出,只需用记录日志即可
|
||||||
return Task.FromResult(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
using FreeRedis;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
using TencentCloud.Mna.V20210119.Models;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Yi.Framework.Rbac.Application.Contracts.Dtos.MonitorCache;
|
||||||
|
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||||
|
{
|
||||||
|
public class MonitorCacheService : ApplicationService, IMonitorCacheService
|
||||||
|
{
|
||||||
|
public IAbpLazyServiceProvider LazyServiceProvider { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存前缀
|
||||||
|
/// </summary>
|
||||||
|
private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDistributedCacheOptions>>().Value.KeyPrefix;
|
||||||
|
|
||||||
|
private bool EnableRedisCache
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var redisEnabled = LazyServiceProvider.LazyGetRequiredService<IConfiguration>()["Redis:IsEnabled"];
|
||||||
|
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 使用懒加载防止报错
|
||||||
|
/// </summary>
|
||||||
|
private IRedisClient RedisClient => LazyServiceProvider.LazyGetRequiredService<IRedisClient>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有key并分组
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("monitor-cache/name")]
|
||||||
|
public List<MonitorCacheNameGetListOutputDto> GetName()
|
||||||
|
{
|
||||||
|
VerifyRedisCacheEnable();
|
||||||
|
var keys = RedisClient.Keys(CacheKeyPrefix + "*");
|
||||||
|
var result = GroupedKeys(keys.ToList());
|
||||||
|
var output = result.Select(x => new MonitorCacheNameGetListOutputDto { CacheName = x }).ToList();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> GroupedKeys(List<string> keys)
|
||||||
|
{
|
||||||
|
HashSet<string> resultSet = new HashSet<string>();
|
||||||
|
foreach (string str in keys)
|
||||||
|
{
|
||||||
|
string[] parts = str.Split(':');
|
||||||
|
|
||||||
|
// 如果字符串中包含冒号,则将第一部分和第二部分进行分组
|
||||||
|
if (parts.Length >= 2)
|
||||||
|
{
|
||||||
|
string group = $"{parts[0]}:{parts[1]}";
|
||||||
|
resultSet.Add(group);
|
||||||
|
}
|
||||||
|
// 如果字符串中不包含冒号,则直接进行分组
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resultSet.Add(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultSet.ToList();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void VerifyRedisCacheEnable()
|
||||||
|
{
|
||||||
|
if (!EnableRedisCache)
|
||||||
|
{
|
||||||
|
throw new UserFriendlyException("后端程序未使用Redis缓存,无法对Redis进行监控,可切换使用Redis");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("monitor-cache/key/{cacaheName}")]
|
||||||
|
public List<string> GetKey(string cacaheName)
|
||||||
|
{
|
||||||
|
VerifyRedisCacheEnable();
|
||||||
|
var output = RedisClient.Keys($"{cacaheName}:*").Select(x => x.RemovePreFix(cacaheName + ":"));
|
||||||
|
return output.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//全部不为空
|
||||||
|
[HttpGet("monitor-cache/value/{cacaheName}/{cacaheKey}")]
|
||||||
|
public MonitorCacheGetListOutputDto GetValue(string cacaheName, string cacaheKey)
|
||||||
|
{
|
||||||
|
var value = RedisClient.HGet($"{cacaheName}:{cacaheKey}", "data");
|
||||||
|
return new MonitorCacheGetListOutputDto() { CacheKey = cacaheKey, CacheName = cacaheName, CacheValue = value };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[HttpDelete("monitor-cache/key/{cacaheName}")]
|
||||||
|
public bool DeleteKey(string cacaheName)
|
||||||
|
{
|
||||||
|
VerifyRedisCacheEnable();
|
||||||
|
RedisClient.Del($"{cacaheName}:*");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("monitor-cache/value/{cacaheName}/{cacaheKey}")]
|
||||||
|
public bool DeleteValue(string cacaheName, string cacaheKey)
|
||||||
|
{
|
||||||
|
RedisClient.Del($"{cacaheName}:{cacaheKey}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("monitor-cache/clear")]
|
||||||
|
public bool DeleteClear()
|
||||||
|
{
|
||||||
|
RedisClient.FlushDb();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ using Volo.Abp.Application.Services;
|
|||||||
using Yi.Framework.Core.Helper;
|
using Yi.Framework.Core.Helper;
|
||||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||||
{
|
{
|
||||||
public class MonitorServerService : ApplicationService, IMonitorServerService
|
public class MonitorServerService : ApplicationService, IMonitorServerService
|
||||||
{
|
{
|
||||||
@@ -7,13 +7,13 @@ using Yi.Framework.Rbac.Application.Contracts.IServices;
|
|||||||
using Yi.Framework.Rbac.Application.SignalRHubs;
|
using Yi.Framework.Rbac.Application.SignalRHubs;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Model;
|
using Yi.Framework.Rbac.Domain.Shared.Model;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||||
{
|
{
|
||||||
public class OnlineService : ApplicationService, IOnlineService
|
public class OnlineService : ApplicationService, IOnlineService
|
||||||
{
|
{
|
||||||
private ILogger<OnlineService> _logger;
|
private ILogger<OnlineService> _logger;
|
||||||
private IHubContext<OnlineUserHub> _hub;
|
private IHubContext<OnlineHub> _hub;
|
||||||
public OnlineService(ILogger<OnlineService> logger, IHubContext<OnlineUserHub> hub)
|
public OnlineService(ILogger<OnlineService> logger, IHubContext<OnlineHub> hub)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_hub = hub;
|
_hub = hub;
|
||||||
@@ -26,7 +26,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<PagedResultDto<OnlineUserModel>> GetListAsync([FromQuery] OnlineUserModel online)
|
public Task<PagedResultDto<OnlineUserModel>> GetListAsync([FromQuery] OnlineUserModel online)
|
||||||
{
|
{
|
||||||
var data = OnlineUserHub.clientUsers;
|
var data = OnlineHub.clientUsers;
|
||||||
IEnumerable<OnlineUserModel> dataWhere = data.AsEnumerable();
|
IEnumerable<OnlineUserModel> dataWhere = data.AsEnumerable();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(online.Ipaddr))
|
if (!string.IsNullOrEmpty(online.Ipaddr))
|
||||||
@@ -37,7 +37,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
{
|
{
|
||||||
dataWhere = dataWhere.Where((u) => u.UserName!.Contains(online.UserName));
|
dataWhere = dataWhere.Where((u) => u.UserName!.Contains(online.UserName));
|
||||||
}
|
}
|
||||||
return Task.FromResult(new PagedResultDto<OnlineUserModel>() { TotalCount = data.Count, Items = dataWhere.ToList() }) ;
|
return Task.FromResult(new PagedResultDto<OnlineUserModel>() { TotalCount = data.Count, Items = dataWhere.ToList() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
[Route("online/{connnectionId}")]
|
[Route("online/{connnectionId}")]
|
||||||
public async Task<bool> ForceOut(string connnectionId)
|
public async Task<bool> ForceOut(string connnectionId)
|
||||||
{
|
{
|
||||||
if (OnlineUserHub.clientUsers.Exists(u => u.ConnnectionId == connnectionId))
|
if (OnlineHub.clientUsers.Exists(u => u.ConnnectionId == connnectionId))
|
||||||
{
|
{
|
||||||
//前端接受到这个事件后,触发前端自动退出
|
//前端接受到这个事件后,触发前端自动退出
|
||||||
await _hub.Clients.Client(connnectionId).SendAsync("forceOut", "你已被强制退出!");
|
await _hub.Clients.Client(connnectionId).SendAsync("forceOut", "你已被强制退出!");
|
||||||
@@ -11,7 +11,7 @@ using Yi.Framework.Rbac.Application.Contracts.Dtos.Task;
|
|||||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
namespace Yi.Framework.Rbac.Application.Services.Monitor
|
||||||
{
|
{
|
||||||
public class TaskService : ApplicationService, ITaskService
|
public class TaskService : ApplicationService, ITaskService
|
||||||
{
|
{
|
||||||
@@ -19,7 +19,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
private readonly IClock _clock;
|
private readonly IClock _clock;
|
||||||
public TaskService(ISchedulerFactory schedulerFactory, IClock clock)
|
public TaskService(ISchedulerFactory schedulerFactory, IClock clock)
|
||||||
{
|
{
|
||||||
_clock=clock;
|
_clock = clock;
|
||||||
_schedulerFactory = schedulerFactory;
|
_schedulerFactory = schedulerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
Properties = Newtonsoft.Json.JsonConvert.SerializeObject(jobDetail.JobDataMap),
|
Properties = Newtonsoft.Json.JsonConvert.SerializeObject(jobDetail.JobDataMap),
|
||||||
Concurrent = !jobDetail.ConcurrentExecutionDisallowed,
|
Concurrent = !jobDetail.ConcurrentExecutionDisallowed,
|
||||||
Description = jobDetail.Description,
|
Description = jobDetail.Description,
|
||||||
LastRunTime = _clock.Normalize( trigger.GetPreviousFireTimeUtc()?.DateTime??DateTime.MinValue),
|
LastRunTime = _clock.Normalize(trigger.GetPreviousFireTimeUtc()?.DateTime ?? DateTime.MinValue),
|
||||||
NextRunTime = _clock.Normalize(trigger.GetNextFireTimeUtc()?.DateTime ?? DateTime.MinValue),
|
NextRunTime = _clock.Normalize(trigger.GetNextFireTimeUtc()?.DateTime ?? DateTime.MinValue),
|
||||||
AssemblyName = jobDetail.JobType.Assembly.GetName().Name,
|
AssemblyName = jobDetail.JobType.Assembly.GetName().Name,
|
||||||
Status = state.ToString()
|
Status = state.ToString()
|
||||||
@@ -56,7 +56,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
|
|
||||||
if (trigger is ISimpleTrigger simple)
|
if (trigger is ISimpleTrigger simple)
|
||||||
{
|
{
|
||||||
output.TriggerArgs =Math.Round(simple.RepeatInterval.TotalMinutes,2) .ToString() + "分钟";
|
output.TriggerArgs = Math.Round(simple.RepeatInterval.TotalMinutes, 2).ToString() + "分钟";
|
||||||
output.Type = JobTypeEnum.Millisecond;
|
output.Type = JobTypeEnum.Millisecond;
|
||||||
output.Millisecond = simple.RepeatInterval.TotalMilliseconds;
|
output.Millisecond = simple.RepeatInterval.TotalMilliseconds;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
{
|
{
|
||||||
output.TriggerArgs = cron.CronExpressionString!;
|
output.TriggerArgs = cron.CronExpressionString!;
|
||||||
output.Type = JobTypeEnum.Cron;
|
output.Type = JobTypeEnum.Cron;
|
||||||
output.Cron=cron.CronExpressionString;
|
output.Cron = cron.CronExpressionString;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task DeleteAsync(IEnumerable<string> id)
|
public async Task DeleteAsync(IEnumerable<string> id)
|
||||||
{
|
{
|
||||||
var scheduler = await _schedulerFactory.GetScheduler();
|
var scheduler = await _schedulerFactory.GetScheduler();
|
||||||
await scheduler.DeleteJobs(id.Select(x => new JobKey(x)).ToList());
|
await scheduler.DeleteJobs(id.Select(x => new JobKey(x)).ToList());
|
||||||
}
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Volo.Abp.Application.Services;
|
|
||||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.MonitorCache;
|
|
||||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
|
||||||
{
|
|
||||||
public class MonitorCacheService : ApplicationService, IMonitorCacheService
|
|
||||||
{
|
|
||||||
private static List<MonitorCacheNameGetListOutputDto> monitorCacheNames => new List<MonitorCacheNameGetListOutputDto>()
|
|
||||||
{
|
|
||||||
new MonitorCacheNameGetListOutputDto{ CacheName="Yi:Login",Remark="登录验证码"},
|
|
||||||
new MonitorCacheNameGetListOutputDto{ CacheName="Yi:User",Remark="用户信息"}
|
|
||||||
};
|
|
||||||
private Dictionary<string, string> monitorCacheNamesDic => monitorCacheNames.ToDictionary(x => x.CacheName, x => x.Remark);
|
|
||||||
//private CSRedisClient _cacheClient;
|
|
||||||
public MonitorCacheService()
|
|
||||||
{
|
|
||||||
//_cacheClient = redisCacheClient.Client;
|
|
||||||
}
|
|
||||||
//cacheKey value为空,只要name和备注
|
|
||||||
|
|
||||||
public List<MonitorCacheNameGetListOutputDto> GetName()
|
|
||||||
{
|
|
||||||
//固定的
|
|
||||||
return monitorCacheNames;
|
|
||||||
}
|
|
||||||
[HttpGet("key/{cacaheName}")]
|
|
||||||
public List<string> GetKey(string cacaheName)
|
|
||||||
{
|
|
||||||
//var output = _cacheClient.Keys($"{cacaheName}:*");
|
|
||||||
return new List<string>() { "1233124", "3124", "1231251", "12312412" };
|
|
||||||
}
|
|
||||||
|
|
||||||
//全部不为空
|
|
||||||
[HttpGet("value/{cacaheName}/{cacaheKey}")]
|
|
||||||
public MonitorCacheGetListOutputDto GetValue(string cacaheName, string cacaheKey)
|
|
||||||
{
|
|
||||||
//var value = _cacheClient.Get($"{cacaheName}:{cacaheKey}");
|
|
||||||
return new MonitorCacheGetListOutputDto() { CacheKey = cacaheKey, CacheName = cacaheName, CacheValue = "ttt", Remark = monitorCacheNamesDic[cacaheName] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using SqlSugar;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Yi.Framework.Ddd.Application;
|
||||||
|
using Yi.Framework.Rbac.Application.Contracts.Dtos.Notice;
|
||||||
|
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||||
|
using Yi.Framework.Rbac.Application.SignalRHubs;
|
||||||
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Notice服务实现
|
||||||
|
/// </summary>
|
||||||
|
public class NoticeService : YiCrudAppService<NoticeEntity, NoticeGetOutputDto, NoticeGetListOutputDto, Guid, NoticeGetListInput, NoticeCreateInput, NoticeUpdateInput>,
|
||||||
|
INoticeService
|
||||||
|
{
|
||||||
|
private ISqlSugarRepository<NoticeEntity, Guid> _repository;
|
||||||
|
private IHubContext<NoticeHub> _hubContext;
|
||||||
|
public NoticeService(ISqlSugarRepository<NoticeEntity, Guid> repository, IHubContext<NoticeHub> hubContext) : base(repository)
|
||||||
|
{
|
||||||
|
_hubContext = hubContext;
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多查
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override async Task<PagedResultDto<NoticeGetListOutputDto>> GetListAsync(NoticeGetListInput input)
|
||||||
|
{
|
||||||
|
RefAsync<int> total = 0;
|
||||||
|
|
||||||
|
var entities = await _repository._DbQueryable.WhereIF(input.Type is not null, x => x.Type == input.Type)
|
||||||
|
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title!.Contains(input.Title!))
|
||||||
|
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||||
|
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||||
|
return new PagedResultDto<NoticeGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送在线消息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("notice/online/{id}")]
|
||||||
|
public async Task SendOnlineAsync([FromRoute] Guid id)
|
||||||
|
{
|
||||||
|
var entity = await _repository._DbQueryable.FirstAsync(x => x.Id == id);
|
||||||
|
await _hubContext.Clients.All.SendAsync("ReceiveNotice", entity.Type.ToString(), entity.Title, entity.Content);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 发送离线消息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("notice/offline/{id}")]
|
||||||
|
public async Task SendOfflineAsync([FromRoute] Guid id)
|
||||||
|
{
|
||||||
|
//先发送一个在线
|
||||||
|
await SendOnlineAsync(id);
|
||||||
|
|
||||||
|
//然后将所有用户和通知id进行保留记录,判断是否已读还是未读
|
||||||
|
//在首次请求返回全部未读的通知给前端即可
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ using Yi.Framework.Rbac.Application.Contracts.Dtos.LoginLog;
|
|||||||
using Yi.Framework.Rbac.Domain.Entities;
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
||||||
{
|
{
|
||||||
public class LoginLogService : YiCrudAppService<LoginLogEntity, LoginLogGetListOutputDto, Guid, LoginLogGetListInputVo>
|
public class LoginLogService : YiCrudAppService<LoginLogEntity, LoginLogGetListOutputDto, Guid, LoginLogGetListInputVo>
|
||||||
{
|
{
|
||||||
@@ -7,7 +7,7 @@ using Yi.Framework.Rbac.Application.Contracts.IServices;
|
|||||||
using Yi.Framework.Rbac.Domain.Operlog;
|
using Yi.Framework.Rbac.Domain.Operlog;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Application.Services
|
namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// OperationLog服务实现
|
/// OperationLog服务实现
|
||||||
@@ -18,7 +18,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
private ISqlSugarRepository<OperationLogEntity, Guid> _repository;
|
private ISqlSugarRepository<OperationLogEntity, Guid> _repository;
|
||||||
public OperationLogService(ISqlSugarRepository<OperationLogEntity, Guid> repository) : base(repository)
|
public OperationLogService(ISqlSugarRepository<OperationLogEntity, Guid> repository) : base(repository)
|
||||||
{
|
{
|
||||||
_repository=repository;
|
_repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
|
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Volo.Abp.AspNetCore.SignalR;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Application.SignalRHubs
|
||||||
|
{
|
||||||
|
[HubRoute("/hub/notice")]
|
||||||
|
public class NoticeHub : AbpHub
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 由于发布功能,主要是服务端项客户端主动推送
|
||||||
|
/// </summary>
|
||||||
|
public NoticeHub()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,14 +10,14 @@ namespace Yi.Framework.Rbac.Application.SignalRHubs
|
|||||||
{
|
{
|
||||||
[HubRoute("/hub/main")]
|
[HubRoute("/hub/main")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class OnlineUserHub : AbpHub
|
public class OnlineHub : AbpHub
|
||||||
{
|
{
|
||||||
public static readonly List<OnlineUserModel> clientUsers = new();
|
public static readonly List<OnlineUserModel> clientUsers = new();
|
||||||
private readonly static object objLock = new object();
|
private readonly static object objLock = new object();
|
||||||
|
|
||||||
private HttpContext? _httpContext;
|
private HttpContext? _httpContext;
|
||||||
private ILogger<OnlineUserHub> _logger => LoggerFactory.CreateLogger<OnlineUserHub>();
|
private ILogger<OnlineHub> _logger => LoggerFactory.CreateLogger<OnlineHub>();
|
||||||
public OnlineUserHub(IHttpContextAccessor httpContextAccessor)
|
public OnlineHub(IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
_httpContext = httpContextAccessor?.HttpContext;
|
_httpContext = httpContextAccessor?.HttpContext;
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Caches
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Yi:Phone:{Phone}";
|
return $"Phone:{Phone}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Domain.Shared.Caches
|
||||||
|
{
|
||||||
|
public class UserInfoCacheItem
|
||||||
|
{
|
||||||
|
public UserInfoCacheItem(UserRoleMenuDto info) { Info = info; }
|
||||||
|
/// <summary>
|
||||||
|
/// 存储的用户信息
|
||||||
|
/// </summary>
|
||||||
|
public UserRoleMenuDto Info { get; set; }
|
||||||
|
}
|
||||||
|
public class UserInfoCacheKey
|
||||||
|
{
|
||||||
|
public UserInfoCacheKey(Guid userId) { UserId = userId; }
|
||||||
|
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"User:{UserId}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Domain.Shared.Enums
|
||||||
|
{
|
||||||
|
public enum NoticeTypeEnum
|
||||||
|
{
|
||||||
|
[Description("走马灯")]
|
||||||
|
MerryGoRound = 0,
|
||||||
|
[Description("提示弹窗")]
|
||||||
|
Popup = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SqlSugar;
|
||||||
|
using Volo.Abp.Auditing;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Yi.Framework.Core.Data;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Rbac.Domain.Entities
|
||||||
|
{
|
||||||
|
[SugarTable("Notice")]
|
||||||
|
public class NoticeEntity : Entity<Guid>, ISoftDelete, IAuditedObject, IOrderNum, IState
|
||||||
|
{
|
||||||
|
|
||||||
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
|
public override Guid Id { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告标题
|
||||||
|
/// </summary>
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型
|
||||||
|
/// </summary>
|
||||||
|
public NoticeTypeEnum Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内容
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||||
|
public string Content { get; set; }
|
||||||
|
|
||||||
|
public bool IsDeleted { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreationTime { get; set; }
|
||||||
|
|
||||||
|
public Guid? CreatorId { get; set; }
|
||||||
|
|
||||||
|
public Guid? LastModifierId { get; set; }
|
||||||
|
|
||||||
|
public DateTime? LastModificationTime { get; set; }
|
||||||
|
|
||||||
|
public int OrderNum { get; set; }
|
||||||
|
public bool State { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
|||||||
/// 岗位表
|
/// 岗位表
|
||||||
///</summary>
|
///</summary>
|
||||||
[SugarTable("Post")]
|
[SugarTable("Post")]
|
||||||
public partial class PostEntity : Entity<Guid>, ISoftDelete, IAuditedObject, IOrderNum, IState
|
public class PostEntity : Entity<Guid>, ISoftDelete, IAuditedObject, IOrderNum, IState
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Yi.Framework.Rbac.Domain.Entities;
|
|||||||
/// 角色部门关系表
|
/// 角色部门关系表
|
||||||
///</summary>
|
///</summary>
|
||||||
[SugarTable("RoleDept")]
|
[SugarTable("RoleDept")]
|
||||||
public partial class RoleDeptEntity : Entity<Guid>
|
public class RoleDeptEntity : Entity<Guid>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主键
|
/// 主键
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ using Microsoft.AspNetCore.Http;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Volo.Abp;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.Domain.Entities;
|
using Volo.Abp.Domain.Entities;
|
||||||
using Volo.Abp.Domain.Services;
|
using Volo.Abp.Domain.Services;
|
||||||
using Volo.Abp.EventBus.Local;
|
using Volo.Abp.EventBus.Local;
|
||||||
using Volo.Abp.Security.Claims;
|
using Volo.Abp.Security.Claims;
|
||||||
using Volo.Abp.Users;
|
|
||||||
using Yi.Framework.Core.Helper;
|
using Yi.Framework.Core.Helper;
|
||||||
using Yi.Framework.Rbac.Domain.Entities;
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
using Yi.Framework.Rbac.Domain.Repositories;
|
using Yi.Framework.Rbac.Domain.Repositories;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Caches;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Etos;
|
using Yi.Framework.Rbac.Domain.Shared.Etos;
|
||||||
@@ -38,6 +38,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
private UserManager _userManager;
|
private UserManager _userManager;
|
||||||
private ISqlSugarRepository<RoleEntity> _roleRepository;
|
private ISqlSugarRepository<RoleEntity> _roleRepository;
|
||||||
private RefreshJwtOptions _refreshJwtOptions;
|
private RefreshJwtOptions _refreshJwtOptions;
|
||||||
|
|
||||||
public AccountManager(IUserRepository repository
|
public AccountManager(IUserRepository repository
|
||||||
, IHttpContextAccessor httpContextAccessor
|
, IHttpContextAccessor httpContextAccessor
|
||||||
, IOptions<JwtOptions> jwtOptions
|
, IOptions<JwtOptions> jwtOptions
|
||||||
@@ -87,9 +88,9 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
loginEto.UserId = userInfo.User.Id;
|
loginEto.UserId = userInfo.User.Id;
|
||||||
await _localEventBus.PublishAsync(loginEto);
|
await _localEventBus.PublishAsync(loginEto);
|
||||||
}
|
}
|
||||||
|
var accessToken = CreateToken(this.UserInfoToClaim(userInfo));
|
||||||
//将用户信息添加到缓存中,需要考虑的是更改了用户、角色、菜单等整个体系都需要将缓存进行刷新,看具体业务进行选择
|
//将用户信息添加到缓存中,需要考虑的是更改了用户、角色、菜单等整个体系都需要将缓存进行刷新,看具体业务进行选择
|
||||||
|
|
||||||
var accessToken = CreateToken(this.UserInfoToClaim(userInfo));
|
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
@@ -175,11 +176,12 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
{
|
{
|
||||||
userAction.Invoke(user);
|
userAction.Invoke(user);
|
||||||
}
|
}
|
||||||
if (user == null)
|
//这里为了兼容解决数据库开启了大小写不敏感问题,还要将用户名进行二次效验
|
||||||
|
if (user != null&&user.UserName==userName)
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.Caching.FreeRedis\Yi.Framework.Caching.FreeRedis.csproj" />
|
||||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\Yi.Framework.Rbac.Domain.Shared\Yi.Framework.Rbac.Domain.Shared.csproj" />
|
<ProjectReference Include="..\Yi.Framework.Rbac.Domain.Shared\Yi.Framework.Rbac.Domain.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Volo.Abp.AspNetCore.SignalR;
|
|||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.Domain;
|
using Volo.Abp.Domain;
|
||||||
using Volo.Abp.Modularity;
|
using Volo.Abp.Modularity;
|
||||||
|
using Yi.Framework.Caching.FreeRedis;
|
||||||
using Yi.Framework.Mapster;
|
using Yi.Framework.Mapster;
|
||||||
using Yi.Framework.Rbac.Domain.Authorization;
|
using Yi.Framework.Rbac.Domain.Authorization;
|
||||||
using Yi.Framework.Rbac.Domain.Operlog;
|
using Yi.Framework.Rbac.Domain.Operlog;
|
||||||
@@ -13,6 +14,7 @@ namespace Yi.Framework.Rbac.Domain
|
|||||||
{
|
{
|
||||||
[DependsOn(
|
[DependsOn(
|
||||||
typeof(YiFrameworkRbacDomainSharedModule),
|
typeof(YiFrameworkRbacDomainSharedModule),
|
||||||
|
typeof(YiFrameworkCachingFreeRedisModule),
|
||||||
|
|
||||||
typeof(AbpAspNetCoreSignalRModule),
|
typeof(AbpAspNetCoreSignalRModule),
|
||||||
typeof(AbpDddDomainModule),
|
typeof(AbpDddDomainModule),
|
||||||
|
|||||||
@@ -1125,6 +1125,75 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//通知公告
|
||||||
|
MenuEntity notice = new MenuEntity(_guidGenerator.Create())
|
||||||
|
{
|
||||||
|
|
||||||
|
MenuName = "通知公告",
|
||||||
|
PermissionCode = "system:notice:list",
|
||||||
|
MenuType = MenuTypeEnum.Menu,
|
||||||
|
Router = "notice",
|
||||||
|
IsShow = true,
|
||||||
|
IsLink = false,
|
||||||
|
IsCache = true,
|
||||||
|
Component = "system/notice/index",
|
||||||
|
MenuIcon = "message",
|
||||||
|
OrderNum = 93,
|
||||||
|
ParentId = system.Id,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
entities.Add(notice);
|
||||||
|
|
||||||
|
MenuEntity noticeQuery = new MenuEntity(_guidGenerator.Create())
|
||||||
|
{
|
||||||
|
|
||||||
|
MenuName = "通知查询",
|
||||||
|
PermissionCode = "system:notice:query",
|
||||||
|
MenuType = MenuTypeEnum.Component,
|
||||||
|
OrderNum = 100,
|
||||||
|
ParentId = notice.Id,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
entities.Add(noticeQuery);
|
||||||
|
|
||||||
|
MenuEntity noticeAdd = new MenuEntity(_guidGenerator.Create())
|
||||||
|
{
|
||||||
|
|
||||||
|
MenuName = "通知新增",
|
||||||
|
PermissionCode = "system:notice:add",
|
||||||
|
MenuType = MenuTypeEnum.Component,
|
||||||
|
OrderNum = 100,
|
||||||
|
ParentId = notice.Id,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
entities.Add(noticeAdd);
|
||||||
|
|
||||||
|
MenuEntity noticeEdit = new MenuEntity(_guidGenerator.Create())
|
||||||
|
{
|
||||||
|
|
||||||
|
MenuName = "通知修改",
|
||||||
|
PermissionCode = "system:notice:edit",
|
||||||
|
MenuType = MenuTypeEnum.Component,
|
||||||
|
OrderNum = 100,
|
||||||
|
ParentId = notice.Id,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
entities.Add(noticeEdit);
|
||||||
|
|
||||||
|
MenuEntity noticeRemove = new MenuEntity(_guidGenerator.Create())
|
||||||
|
{
|
||||||
|
|
||||||
|
MenuName = "通知删除",
|
||||||
|
PermissionCode = "system:notice:remove",
|
||||||
|
MenuType = MenuTypeEnum.Component,
|
||||||
|
OrderNum = 100,
|
||||||
|
ParentId = notice.Id,
|
||||||
|
IsDeleted = false
|
||||||
|
};
|
||||||
|
entities.Add(noticeRemove);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//日志管理
|
//日志管理
|
||||||
MenuEntity log = new MenuEntity(_guidGenerator.Create())
|
MenuEntity log = new MenuEntity(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
@@ -1135,7 +1204,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
IsShow = true,
|
IsShow = true,
|
||||||
IsLink = false,
|
IsLink = false,
|
||||||
MenuIcon = "log",
|
MenuIcon = "log",
|
||||||
OrderNum = 93,
|
OrderNum = 92,
|
||||||
ParentId = system.Id,
|
ParentId = system.Id,
|
||||||
IsDeleted = false
|
IsDeleted = false
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.RateLimiting;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.Uow;
|
using Volo.Abp.Uow;
|
||||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Banner;
|
using Yi.Framework.Bbs.Application.Contracts.Dtos.Banner;
|
||||||
@@ -117,5 +118,19 @@ namespace Yi.Abp.Application.Services
|
|||||||
var entity = new BannerEntity();
|
var entity = new BannerEntity();
|
||||||
var dto = entity.Adapt<BannerGetListOutputDto>();
|
var dto = entity.Adapt<BannerGetListOutputDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 速率限制
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
// [DisableRateLimiting]
|
||||||
|
//[EnableRateLimiting("sliding")]
|
||||||
|
public int GetRateLimiting()
|
||||||
|
{
|
||||||
|
RequestNumber++;
|
||||||
|
return RequestNumber;
|
||||||
|
}
|
||||||
|
private static int RequestNumber { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<ProjectReference Include="..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
|
<ProjectReference Include="..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
|
||||||
<ProjectReference Include="..\..\module\audit-logging\Yi.Framework.AuditLogging.SqlSugarCore\Yi.Framework.AuditLogging.SqlSugarCore.csproj" />
|
<ProjectReference Include="..\..\module\audit-logging\Yi.Framework.AuditLogging.SqlSugarCore\Yi.Framework.AuditLogging.SqlSugarCore.csproj" />
|
||||||
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.SqlSugarCore\Yi.Framework.Bbs.SqlSugarCore.csproj" />
|
<ProjectReference Include="..\..\module\bbs\Yi.Framework.Bbs.SqlSugarCore\Yi.Framework.Bbs.SqlSugarCore.csproj" />
|
||||||
|
<ProjectReference Include="..\..\module\code-gen\Yi.Framework.CodeGen.SqlSugarCore\Yi.Framework.CodeGen.SqlSugarCore.csproj" />
|
||||||
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.SqlSugarCore\Yi.Framework.Rbac.SqlSugarCore.csproj" />
|
<ProjectReference Include="..\..\module\rbac\Yi.Framework.Rbac.SqlSugarCore\Yi.Framework.Rbac.SqlSugarCore.csproj" />
|
||||||
<ProjectReference Include="..\..\module\tenant-management\Yi.Framework.TenantManagement.SqlSugarCore\Yi.Framework.TenantManagement.SqlSugarCore.csproj" />
|
<ProjectReference Include="..\..\module\tenant-management\Yi.Framework.TenantManagement.SqlSugarCore\Yi.Framework.TenantManagement.SqlSugarCore.csproj" />
|
||||||
<ProjectReference Include="..\Yi.Abp.Domain\Yi.Abp.Domain.csproj" />
|
<ProjectReference Include="..\Yi.Abp.Domain\Yi.Abp.Domain.csproj" />
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Yi.Abp.Domain;
|
|||||||
using Yi.Abp.SqlSugarCore;
|
using Yi.Abp.SqlSugarCore;
|
||||||
using Yi.Framework.AuditLogging.SqlSugarCore;
|
using Yi.Framework.AuditLogging.SqlSugarCore;
|
||||||
using Yi.Framework.Bbs.SqlSugarCore;
|
using Yi.Framework.Bbs.SqlSugarCore;
|
||||||
|
using Yi.Framework.CodeGen.SqlSugarCore;
|
||||||
using Yi.Framework.Mapster;
|
using Yi.Framework.Mapster;
|
||||||
using Yi.Framework.Rbac.SqlSugarCore;
|
using Yi.Framework.Rbac.SqlSugarCore;
|
||||||
using Yi.Framework.SqlSugarCore;
|
using Yi.Framework.SqlSugarCore;
|
||||||
@@ -17,6 +18,7 @@ namespace Yi.Abp.SqlsugarCore
|
|||||||
|
|
||||||
typeof(YiFrameworkRbacSqlSugarCoreModule),
|
typeof(YiFrameworkRbacSqlSugarCoreModule),
|
||||||
typeof(YiFrameworkBbsSqlSugarCoreModule),
|
typeof(YiFrameworkBbsSqlSugarCoreModule),
|
||||||
|
typeof(YiFrameworkCodeGenSqlSugarCoreModule),
|
||||||
|
|
||||||
typeof(YiFrameworkAuditLoggingSqlSugarCoreModule),
|
typeof(YiFrameworkAuditLoggingSqlSugarCoreModule),
|
||||||
typeof(YiFrameworkTenantManagementSqlSugarCoreModule),
|
typeof(YiFrameworkTenantManagementSqlSugarCoreModule),
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using SqlSugar;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using SqlSugar;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
using Yi.Framework.Rbac.SqlSugarCore;
|
using Yi.Framework.Rbac.SqlSugarCore;
|
||||||
|
using Yi.Framework.SqlSugarCore;
|
||||||
|
|
||||||
namespace Yi.Abp.SqlSugarCore
|
namespace Yi.Abp.SqlSugarCore
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System.Text;
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.RateLimiting;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.RateLimiting;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
@@ -84,10 +87,12 @@ namespace Yi.Abp.Web
|
|||||||
});
|
});
|
||||||
|
|
||||||
//设置缓存不要过期,默认滑动20分钟
|
//设置缓存不要过期,默认滑动20分钟
|
||||||
Configure<AbpDistributedCacheOptions>(cacheOptions =>
|
Configure<AbpDistributedCacheOptions>(cacheOptions =>
|
||||||
{
|
{
|
||||||
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration =null;
|
cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = null;
|
||||||
});
|
//缓存key前缀
|
||||||
|
cacheOptions.KeyPrefix = "Yi:";
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Configure<AbpAntiForgeryOptions>(options =>
|
Configure<AbpAntiForgeryOptions>(options =>
|
||||||
@@ -133,24 +138,62 @@ namespace Yi.Abp.Web
|
|||||||
//options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
|
//options.TenantResolvers.RemoveAll(x => x.Name == CookieTenantResolveContributor.ContributorName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//速率限制
|
||||||
|
//每60秒限制100个请求,滑块添加,分6段
|
||||||
|
service.AddRateLimiter(_ =>
|
||||||
|
{
|
||||||
|
_.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||||
|
_.OnRejected = (context, _) =>
|
||||||
|
{
|
||||||
|
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
|
||||||
|
{
|
||||||
|
context.HttpContext.Response.Headers.RetryAfter =
|
||||||
|
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
}
|
||||||
|
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
|
||||||
|
context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
|
||||||
|
|
||||||
|
return new ValueTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
//全局使用,链式表达式
|
||||||
|
_.GlobalLimiter = PartitionedRateLimiter.CreateChained(
|
||||||
|
PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
|
||||||
|
{
|
||||||
|
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
|
||||||
|
|
||||||
|
return RateLimitPartition.GetSlidingWindowLimiter
|
||||||
|
(userAgent, _ =>
|
||||||
|
new SlidingWindowRateLimiterOptions
|
||||||
|
{
|
||||||
|
PermitLimit = 100,
|
||||||
|
Window = TimeSpan.FromSeconds(60),
|
||||||
|
SegmentsPerWindow = 6,
|
||||||
|
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//jwt鉴权
|
//jwt鉴权
|
||||||
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
|
var jwtOptions = configuration.GetSection(nameof(JwtOptions)).Get<JwtOptions>();
|
||||||
var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();
|
var refreshJwtOptions = configuration.GetSection(nameof(RefreshJwtOptions)).Get<RefreshJwtOptions>();
|
||||||
|
|
||||||
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
.AddJwtBearer(options =>
|
.AddJwtBearer(options =>
|
||||||
{
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
{
|
||||||
ClockSkew = TimeSpan.Zero,
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
ValidateIssuerSigningKey = true,
|
{
|
||||||
ValidIssuer = jwtOptions.Issuer,
|
ClockSkew = TimeSpan.Zero,
|
||||||
ValidAudience = jwtOptions.Audience,
|
ValidateIssuerSigningKey = true,
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
|
ValidIssuer = jwtOptions.Issuer,
|
||||||
};
|
ValidAudience = jwtOptions.Audience,
|
||||||
options.Events = new JwtBearerEvents
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey))
|
||||||
{
|
};
|
||||||
OnMessageReceived = context =>
|
options.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
OnMessageReceived = context =>
|
||||||
{
|
{
|
||||||
var accessToken = context.Request.Query["access_token"];
|
var accessToken = context.Request.Query["access_token"];
|
||||||
if (!string.IsNullOrEmpty(accessToken))
|
if (!string.IsNullOrEmpty(accessToken))
|
||||||
@@ -159,21 +202,21 @@ namespace Yi.Abp.Web
|
|||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.AddJwtBearer(TokenTypeConst.Refresh, options =>
|
.AddJwtBearer(TokenTypeConst.Refresh, options =>
|
||||||
{
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
{
|
||||||
ClockSkew = TimeSpan.Zero,
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
ValidateIssuerSigningKey = true,
|
{
|
||||||
ValidIssuer = refreshJwtOptions.Issuer,
|
ClockSkew = TimeSpan.Zero,
|
||||||
ValidAudience = refreshJwtOptions.Audience,
|
ValidateIssuerSigningKey = true,
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
ValidIssuer = refreshJwtOptions.Issuer,
|
||||||
};
|
ValidAudience = refreshJwtOptions.Audience,
|
||||||
options.Events = new JwtBearerEvents
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
||||||
{
|
};
|
||||||
OnMessageReceived = context =>
|
options.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
OnMessageReceived = context =>
|
||||||
{
|
{
|
||||||
var refresh_token = context.Request.Headers["refresh_token"];
|
var refresh_token = context.Request.Headers["refresh_token"];
|
||||||
if (!string.IsNullOrEmpty(refresh_token))
|
if (!string.IsNullOrEmpty(refresh_token))
|
||||||
@@ -189,17 +232,17 @@ namespace Yi.Abp.Web
|
|||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})
|
})
|
||||||
.AddQQ(options =>
|
.AddQQ(options =>
|
||||||
{
|
{
|
||||||
configuration.GetSection("OAuth:QQ").Bind(options);
|
configuration.GetSection("OAuth:QQ").Bind(options);
|
||||||
})
|
})
|
||||||
.AddGitee(options =>
|
.AddGitee(options =>
|
||||||
{
|
{
|
||||||
configuration.GetSection("OAuth:Gitee").Bind(options);
|
configuration.GetSection("OAuth:Gitee").Bind(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
//授权
|
//授权
|
||||||
context.Services.AddAuthorization();
|
context.Services.AddAuthorization();
|
||||||
@@ -219,6 +262,9 @@ namespace Yi.Abp.Web
|
|||||||
//跨域
|
//跨域
|
||||||
app.UseCors(DefaultCorsPolicyName);
|
app.UseCors(DefaultCorsPolicyName);
|
||||||
|
|
||||||
|
//速率限制
|
||||||
|
app.UseRateLimiter();
|
||||||
|
|
||||||
//无感token,先刷新再鉴权
|
//无感token,先刷新再鉴权
|
||||||
app.UseRefreshToken();
|
app.UseRefreshToken();
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
"EnabledSqlLog": true,
|
"EnabledSqlLog": true,
|
||||||
"EnabledDbSeed": true,
|
"EnabledDbSeed": true,
|
||||||
//SAAS多租户
|
//SAAS多租户
|
||||||
"EnabledSaasMultiTenancy":false
|
"EnabledSaasMultiTenancy": false
|
||||||
//读写分离地址
|
//读写分离地址
|
||||||
//"ReadUrl": [
|
//"ReadUrl": [
|
||||||
// "DataSource=[xxxx]", //Sqlite
|
// "DataSource=[xxxx]", //Sqlite
|
||||||
@@ -32,6 +32,12 @@
|
|||||||
//]
|
//]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//redis使用freeesql参数在“FreeSqlOptions的ConnectionStringBuilder中”
|
||||||
|
"Redis": {
|
||||||
|
"IsEnabled": false,
|
||||||
|
"Configuration": "127.0.0.1:6379,password=123,defaultDatabase=13"
|
||||||
|
},
|
||||||
|
|
||||||
//鉴权
|
//鉴权
|
||||||
"JwtOptions": {
|
"JwtOptions": {
|
||||||
"Issuer": "https://ccnetcore.com",
|
"Issuer": "https://ccnetcore.com",
|
||||||
@@ -47,6 +53,7 @@
|
|||||||
"ExpiresMinuteTime": 172800
|
"ExpiresMinuteTime": 172800
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
//第三方登录
|
//第三方登录
|
||||||
"OAuth": {
|
"OAuth": {
|
||||||
//QQ
|
//QQ
|
||||||
|
|||||||
Binary file not shown.
80
Yi.Bbs.Vue3/package-lock.json
generated
80
Yi.Bbs.Vue3/package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.1.0",
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
|
"@lucky-canvas/vue": "^0.1.11",
|
||||||
"@microsoft/signalr": "^8.0.0",
|
"@microsoft/signalr": "^8.0.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
@@ -855,6 +856,51 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@lucky-canvas/vue": {
|
||||||
|
"version": "0.1.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz",
|
||||||
|
"integrity": "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0",
|
||||||
|
"lucky-canvas": "^1.7.23",
|
||||||
|
"vue-demi": "^0.7.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^2.0.0 || >=3.0.0-rc.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@lucky-canvas/vue/node_modules/@vue/composition-api": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": ">= 2.5 < 2.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@lucky-canvas/vue/node_modules/vue-demi": {
|
||||||
|
"version": "0.7.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz",
|
||||||
|
"integrity": "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-beta.1",
|
||||||
|
"vue": "^2.6.0 || >=3.0.0-rc.1"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@microsoft/signalr": {
|
"node_modules/@microsoft/signalr": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
|
||||||
@@ -2673,6 +2719,11 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucky-canvas": {
|
||||||
|
"version": "1.7.27",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz",
|
||||||
|
"integrity": "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
|
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
|
||||||
@@ -4617,6 +4668,30 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@lucky-canvas/vue": {
|
||||||
|
"version": "0.1.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz",
|
||||||
|
"integrity": "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/composition-api": "^1.0.0",
|
||||||
|
"lucky-canvas": "^1.7.23",
|
||||||
|
"vue-demi": "^0.7.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"vue-demi": {
|
||||||
|
"version": "0.7.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz",
|
||||||
|
"integrity": "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@microsoft/signalr": {
|
"@microsoft/signalr": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz",
|
||||||
@@ -6128,6 +6203,11 @@
|
|||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lucky-canvas": {
|
||||||
|
"version": "1.7.27",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz",
|
||||||
|
"integrity": "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
|
||||||
|
},
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
|
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.1.0",
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
|
"@lucky-canvas/vue": "^0.1.11",
|
||||||
"@microsoft/signalr": "^8.0.0",
|
"@microsoft/signalr": "^8.0.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import signalR from "@/utils/signalR";
|
import signalR from "@/utils/signalR";
|
||||||
|
import noticeSignalR from "@/utils/noticeSignalR";
|
||||||
import useConfigStore from "@/stores/config";
|
import useConfigStore from "@/stores/config";
|
||||||
import { ElConfigProvider } from "element-plus";
|
import { ElConfigProvider } from "element-plus";
|
||||||
import useUserStore from "@/stores/user.js";
|
import useUserStore from "@/stores/user.js";
|
||||||
@@ -25,9 +26,8 @@ if (loading !== null) {
|
|||||||
//加载全局信息
|
//加载全局信息
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await configStore.getConfig();
|
await configStore.getConfig();
|
||||||
// setInterval(() => {
|
noticeSignalR.close();
|
||||||
// console.log("token的值:"+tokenValue.value);
|
noticeSignalR.init(`notice`);
|
||||||
// }, 1000); // 1000毫秒,即1秒
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,3 +13,10 @@ export function signInRecord() {
|
|||||||
method: "get"
|
method: "get"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function luckyWheel() {
|
||||||
|
return request({
|
||||||
|
url: "/lucky/wheel",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<el-icon><Memo /></el-icon>
|
<el-icon><Memo /></el-icon>
|
||||||
<span>任务列表</span>
|
<span>任务列表</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item index="4" :route="{path:'/activity/sign'}">
|
<el-menu-item index="4" :route="{path:'/activity/lucky'}">
|
||||||
<el-icon><HelpFilled /></el-icon>
|
<el-icon><HelpFilled /></el-icon>
|
||||||
<span>大转盘</span>
|
<span>大转盘</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import "@/assets/styles/index.scss"; // global css
|
|||||||
|
|
||||||
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
||||||
import directive from "./directive"; // directive
|
import directive from "./directive"; // directive
|
||||||
|
import VueLuckyCanvas from '@lucky-canvas/vue'
|
||||||
|
|
||||||
import "./permission";
|
import "./permission";
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ import "./permission";
|
|||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
directive(app);
|
directive(app);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
app.use(VueLuckyCanvas);
|
||||||
await router.isReady();
|
await router.isReady();
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -122,6 +122,14 @@ const router = createRouter({
|
|||||||
title: "等级",
|
title: "等级",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "lucky",
|
||||||
|
path: "lucky",
|
||||||
|
component: () => import("../views/lucky/Index.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "大转盘",
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },
|
{ path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },
|
||||||
|
|||||||
107
Yi.Bbs.Vue3/src/utils/noticeSignalR.js
Normal file
107
Yi.Bbs.Vue3/src/utils/noticeSignalR.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// 官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2&tabs=visual-studio
|
||||||
|
import * as signalR from "@microsoft/signalr";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// signalR对象
|
||||||
|
SR: {},
|
||||||
|
// 失败连接重试次数
|
||||||
|
failNum: 4,
|
||||||
|
async init(url) {
|
||||||
|
const connection = new signalR.HubConnectionBuilder()
|
||||||
|
.withUrl(`${import.meta.env.VITE_APP_BASE_WS}/` + url)
|
||||||
|
.withAutomaticReconnect() //自动重新连接
|
||||||
|
.configureLogging(signalR.LogLevel.Information)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.SR = connection;
|
||||||
|
// 断线重连
|
||||||
|
connection.onclose(async () => {
|
||||||
|
console.log("断开连接了");
|
||||||
|
console.assert(
|
||||||
|
connection.state === signalR.HubConnectionState.Disconnected
|
||||||
|
);
|
||||||
|
// 建议用户重新刷新浏览器
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.onreconnected(() => {
|
||||||
|
console.log("断线重新连接成功");
|
||||||
|
});
|
||||||
|
this.receiveMsg(connection);
|
||||||
|
// 启动
|
||||||
|
await this.start();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 调用 this.signalR.start().then(async () => { await this.SR.invoke("method")})
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async close() {
|
||||||
|
try {
|
||||||
|
var that = this;
|
||||||
|
await this.SR.stop();
|
||||||
|
this.SR = {};
|
||||||
|
} catch { }
|
||||||
|
},
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//使用async和await 或 promise的then 和catch 处理来自服务端的异常
|
||||||
|
await this.SR.start();
|
||||||
|
//console.assert(this.SR.state === signalR.HubConnectionState.Connected);
|
||||||
|
//console.log('signalR 连接成功了', this.SR.state);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
that.failNum--;
|
||||||
|
//console.log(`失败重试剩余次数${that.failNum}`, error)
|
||||||
|
if (that.failNum > 0) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await this.SR.start();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 接收消息处理
|
||||||
|
receiveMsg(connection) {
|
||||||
|
connection.on("receiveNotice", (type, title, content) => {
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "MerryGoRound":
|
||||||
|
ElNotification({
|
||||||
|
title: title,
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
message: content,
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case "Popup":
|
||||||
|
ElNotification({
|
||||||
|
title: title,
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
message: content,
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// connection.on("onlineNum", (data) => {
|
||||||
|
// store.dispatch("socket/changeOnlineNum", data);
|
||||||
|
// });
|
||||||
|
// // 接收欢迎语
|
||||||
|
// connection.on("welcome", (data) => {
|
||||||
|
// console.log('welcome', data)
|
||||||
|
// Notification.info(data)
|
||||||
|
// });
|
||||||
|
// // 接收后台手动推送消息
|
||||||
|
// connection.on("receiveNotice", (title, data) => {
|
||||||
|
// Notification({
|
||||||
|
// type: 'info',
|
||||||
|
// title: title,
|
||||||
|
// message: data,
|
||||||
|
// dangerouslyUseHTMLString: true,
|
||||||
|
// duration: 0
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -92,7 +92,7 @@ if(registerForm.password!=passwordConfirm.value)
|
|||||||
});
|
});
|
||||||
|
|
||||||
//成功
|
//成功
|
||||||
if (response!=undefined) {
|
if (response.status==204) {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: `恭喜!${registerForm.userName},注册成功!请登录!`,
|
message: `恭喜!${registerForm.userName},注册成功!请登录!`,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
|||||||
@@ -39,9 +39,10 @@ import {getList,upgrade} from '@/apis/levelApi.js'
|
|||||||
import {getBbsUserProfile} from '@/apis/userApi.js'
|
import {getBbsUserProfile} from '@/apis/userApi.js'
|
||||||
import { ref,onMounted, reactive,computed } from 'vue'
|
import { ref,onMounted, reactive,computed } from 'vue'
|
||||||
import useAuths from '@/hooks/useAuths.js';
|
import useAuths from '@/hooks/useAuths.js';
|
||||||
const { isLogin,currentUserInfo } = useAuths();
|
import useUserStore from "@/stores/user";
|
||||||
|
const { isLogin } = useAuths();
|
||||||
const userInfo=ref({});
|
const userInfo=ref({});
|
||||||
|
const currentUserInfo=useUserStore();
|
||||||
const levelData =ref([]);
|
const levelData =ref([]);
|
||||||
const moneyNum=ref(1);
|
const moneyNum=ref(1);
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ const loadLevelData= async () => {
|
|||||||
const loadUserInfoData=async()=>{
|
const loadUserInfoData=async()=>{
|
||||||
if(isLogin)
|
if(isLogin)
|
||||||
{
|
{
|
||||||
const {data}= await getBbsUserProfile(currentUserInfo.value.id);
|
const {data}= await getBbsUserProfile(currentUserInfo.id);
|
||||||
userInfo.value=data;
|
userInfo.value=data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
118
Yi.Bbs.Vue3/src/views/lucky/Index.vue
Normal file
118
Yi.Bbs.Vue3/src/views/lucky/Index.vue
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>谨记人生赌博,不如理性规划</h2>
|
||||||
|
<h3>50钱钱一次,我的钱钱:{{ userInfo?.money ?? '未登录' }}</h3>
|
||||||
|
<LuckyWheel class="wheel" ref="myLucky" width="500px" height="500px" :prizes="prizes" :blocks="blocks"
|
||||||
|
:buttons="buttons" @start="startCallback" @end="endCallback" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import useAuths from '@/hooks/useAuths.js';
|
||||||
|
const { isLogin } = useAuths();
|
||||||
|
import { getBbsUserProfile } from '@/apis/userApi.js'
|
||||||
|
import { luckyWheel } from '@/apis/integralApi.js'
|
||||||
|
import useUserStore from "@/stores/user";
|
||||||
|
const userInfo = ref({});
|
||||||
|
const currentUserInfo=useUserStore();
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadUserInfoData();
|
||||||
|
})
|
||||||
|
const loadUserInfoData = async () => {
|
||||||
|
if (isLogin) {
|
||||||
|
const { data } = await getBbsUserProfile(currentUserInfo.id);
|
||||||
|
userInfo.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const blocks = [{ padding: '13px', background: '#617df2' }];
|
||||||
|
const prizes = [
|
||||||
|
{ fonts: [{ text: '啥也没有', top: '10%' }], background: '#e9e8fe' },
|
||||||
|
{ fonts: [{ text: '10', top: '10%' }], background: '#b8c5f2' },
|
||||||
|
{ fonts: [{ text: '30', top: '10%' }], background: '#e9e8fe' },
|
||||||
|
{ fonts: [{ text: '50', top: '10%' }], background: '#b8c5f2' },
|
||||||
|
{ fonts: [{ text: '80', top: '10%' }], background: '#e9e8fe' },
|
||||||
|
{ fonts: [{ text: '100', top: '10%' }], background: '#b8c5f2' },
|
||||||
|
{ fonts: [{ text: '150', top: '10%' }], background: '#e9e8fe' },
|
||||||
|
{ fonts: [{ text: '200', top: '10%' }], background: '#b8c5f2' },
|
||||||
|
{ fonts: [{ text: '300', top: '10%' }], background: '#e9e8fe' },
|
||||||
|
{ fonts: [{ text: '666', top: '10%' }], background: '#FAD400' }
|
||||||
|
];
|
||||||
|
const buttons = [{
|
||||||
|
radius: '35%',
|
||||||
|
background: '#8a9bf3',
|
||||||
|
pointer: true,
|
||||||
|
fonts: [{ text: '启动', top: '-10px' }]
|
||||||
|
}];
|
||||||
|
|
||||||
|
const myLucky = ref(null);
|
||||||
|
// 点击抽奖按钮会触发star回调
|
||||||
|
const startCallback = () => {
|
||||||
|
var index =0;
|
||||||
|
// 调用抽奖组件的play方法开始游戏
|
||||||
|
if (!isLogin) {
|
||||||
|
ElMessage({
|
||||||
|
message: '请登录后启动!',
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'每次启动需要消耗50钱钱,确定要启动吗?',
|
||||||
|
'警告',
|
||||||
|
{
|
||||||
|
confirmButtonText: '启动',
|
||||||
|
cancelButtonText: '放弃',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async () => {
|
||||||
|
myLucky.value.play()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//等待3秒
|
||||||
|
// 模拟调用接口异步抽奖
|
||||||
|
setTimeout(() => {
|
||||||
|
// 假设后端返回的中奖索引是0
|
||||||
|
// 调用stop停止旋转并传递中奖索引
|
||||||
|
}, 3000)
|
||||||
|
index= (await luckyWheel()).data;
|
||||||
|
myLucky.value.stop(index)
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '成功克制',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
};
|
||||||
|
// 抽奖结束会触发end回调
|
||||||
|
const endCallback = async (prize) => {
|
||||||
|
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `恭喜你抽中了[${prize.fonts[0].text}]`,
|
||||||
|
})
|
||||||
|
await loadUserInfoData();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.wheel {
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
|
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
|
||||||
import { signIn, signInRecord } from "@/apis/integralApi.js";
|
import { signIn, signInRecord } from "@/apis/integralApi.js";
|
||||||
import useAuths from "@/hooks/useAuths";
|
import useAuths from "@/hooks/useAuths";
|
||||||
|
|
||||||
const { isLogin } = useAuths();
|
const { isLogin } = useAuths();
|
||||||
const number=ref(0);
|
const number=ref(0);
|
||||||
const signInData=ref([]);
|
const signInData=ref([]);
|
||||||
|
|||||||
@@ -286,6 +286,15 @@
|
|||||||
"@jridgewell/resolve-uri" "3.1.0"
|
"@jridgewell/resolve-uri" "3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||||
|
|
||||||
|
"@lucky-canvas/vue@^0.1.11":
|
||||||
|
"integrity" "sha512-5vm0txSKRBtMgrE/HZEvw1joSTx9NTdAkc8tBp/aX0LxyhQtiTVBLsRgdYUK/OiURCL8bo+046BTGnV+Q4JFlg=="
|
||||||
|
"resolved" "https://registry.npmmirror.com/@lucky-canvas/vue/-/vue-0.1.11.tgz"
|
||||||
|
"version" "0.1.11"
|
||||||
|
dependencies:
|
||||||
|
"@vue/composition-api" "^1.0.0"
|
||||||
|
"lucky-canvas" "^1.7.23"
|
||||||
|
"vue-demi" "^0.7.4"
|
||||||
|
|
||||||
"@microsoft/signalr@^8.0.0":
|
"@microsoft/signalr@^8.0.0":
|
||||||
"integrity" "sha512-K/wS/VmzRWePCGqGh8MU8OWbS1Zvu7DG7LSJS62fBB8rJUXwwj4axQtqrAAwKGUZHQF6CuteuQR9xMsVpM2JNA=="
|
"integrity" "sha512-K/wS/VmzRWePCGqGh8MU8OWbS1Zvu7DG7LSJS62fBB8rJUXwwj4axQtqrAAwKGUZHQF6CuteuQR9xMsVpM2JNA=="
|
||||||
"resolved" "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz"
|
"resolved" "https://registry.npmmirror.com/@microsoft/signalr/-/signalr-8.0.0.tgz"
|
||||||
@@ -475,6 +484,11 @@
|
|||||||
"@vue/compiler-dom" "3.2.47"
|
"@vue/compiler-dom" "3.2.47"
|
||||||
"@vue/shared" "3.2.47"
|
"@vue/shared" "3.2.47"
|
||||||
|
|
||||||
|
"@vue/composition-api@^1.0.0", "@vue/composition-api@^1.0.0-beta.1":
|
||||||
|
"integrity" "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw=="
|
||||||
|
"resolved" "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz"
|
||||||
|
"version" "1.7.2"
|
||||||
|
|
||||||
"@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.5.0":
|
"@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.5.0":
|
||||||
"integrity" "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
"integrity" "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
||||||
"resolved" "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz"
|
"resolved" "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz"
|
||||||
@@ -1499,6 +1513,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"yallist" "^4.0.0"
|
"yallist" "^4.0.0"
|
||||||
|
|
||||||
|
"lucky-canvas@^1.7.23":
|
||||||
|
"integrity" "sha512-Ftz6qD+863bI7xijBmZg3dw3cNEc7odPr70EZQcGA14y3TgTAzH65HPosOCd6kKUlMwhntBaHMx3onoj9MtJRQ=="
|
||||||
|
"resolved" "https://registry.npmmirror.com/lucky-canvas/-/lucky-canvas-1.7.27.tgz"
|
||||||
|
"version" "1.7.27"
|
||||||
|
|
||||||
"magic-string@^0.25.7":
|
"magic-string@^0.25.7":
|
||||||
"integrity" "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="
|
"integrity" "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="
|
||||||
"resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz"
|
"resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz"
|
||||||
@@ -2239,6 +2258,11 @@
|
|||||||
"resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz"
|
"resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz"
|
||||||
"version" "0.13.11"
|
"version" "0.13.11"
|
||||||
|
|
||||||
|
"vue-demi@^0.7.4":
|
||||||
|
"integrity" "sha512-eFSQSvbQdY7C9ujOzvM6tn7XxwLjn0VQDXQsiYBLBwf28Na+2nTQR4BBBcomhmdP6mmHlBKAwarq6a0BPG87hQ=="
|
||||||
|
"resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.7.5.tgz"
|
||||||
|
"version" "0.7.5"
|
||||||
|
|
||||||
"vue-router@^4.1.6":
|
"vue-router@^4.1.6":
|
||||||
"integrity" "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ=="
|
"integrity" "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ=="
|
||||||
"resolved" "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz"
|
"resolved" "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz"
|
||||||
@@ -2246,7 +2270,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-api" "^6.4.5"
|
"@vue/devtools-api" "^6.4.5"
|
||||||
|
|
||||||
"vue@^2.6.14 || ^3.2.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.2.0", "vue@^3.2.23", "vue@^3.2.25", "vue@^3.2.47", "vue@2 || 3", "vue@3.2.47":
|
"vue@^2.0.0 || >=3.0.0-rc.0", "vue@^2.6.0 || >=3.0.0-rc.1", "vue@^2.6.14 || ^3.2.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.2.0", "vue@^3.2.23", "vue@^3.2.25", "vue@^3.2.47", "vue@>= 2.5 < 2.7", "vue@2 || 3", "vue@3.2.47":
|
||||||
"integrity" "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ=="
|
"integrity" "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ=="
|
||||||
"resolved" "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz"
|
"resolved" "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz"
|
||||||
"version" "3.2.47"
|
"version" "3.2.47"
|
||||||
|
|||||||
41
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/00.模块与项目.md
Normal file
41
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/00.模块与项目.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
## 模块与项目
|
||||||
|
意框架是一个基于Abp.VNext的框架,完美使用模块化理念进行开发。既然是模块化开发,就有`项目`与`项目`的概念。
|
||||||
|
|
||||||
|
很多人问到了我,我的代码应该放到哪里,其实是没有分清楚模块与项目,弄清楚这个,再下手撸码,才更有方向。
|
||||||
|
|
||||||
|
其实不必一堆概念,只需要心中思考一下
|
||||||
|
|
||||||
|
> 我接下来要开发的业务是否有必要被其他项目依赖使用?
|
||||||
|
|
||||||
|
例如:内置的Rbac模块、Bbs模块,单独具备权限管理和社区论坛的功能,公开给大家复用引用,这就可以当成一个模块
|
||||||
|
|
||||||
|
`但是`,有时候如果我不认为他有必要复用,就是公司的一个内部系统,想要快速开发并交付,要同时具备权限管理、商城、审批等各种功能,那就直接当一个项目开发即可,不一定需要将各个模块拆的太散
|
||||||
|
|
||||||
|
> 这个划分的界限,是由项目来决定
|
||||||
|
|
||||||
|
注意:模块的代码与项目的代码结构几乎没有区别
|
||||||
|
|
||||||
|
这意味,有一个最好的方式,先将业务全部写在项目中,等稳定之后,在复制抽象到模块中,完全没有问题。
|
||||||
|
|
||||||
|
### 模块的优缺点
|
||||||
|
- 优点:高度抽象复用
|
||||||
|
- 缺点:肉眼可见的程序集增加、维护成本更高
|
||||||
|
|
||||||
|
### 模块
|
||||||
|

|
||||||
|
|
||||||
|
代码位置放在`module`目录下,单独建立一个自己的模块名称,可使用`脚手架使用`将默认代码生成在这里。
|
||||||
|
|
||||||
|
### 项目
|
||||||
|

|
||||||
|
|
||||||
|
框架内置一个host项目,代码位置存放在`src`中,直接使用即可,如果想更换命名,可以使用上一节的`脚手架使用`。
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
> 由于很多人询问我这个问题,所以单独写一篇,方便大家理解。
|
||||||
|
|
||||||
|
先区分模块还是项目,然后代码写到对应的位置即可
|
||||||
|
|
||||||
|
理论上,按这套规则意味着,只有在自己的`module`、`src`下才需要写代码,其他地方都是内置好了的,通过继承、实现等方式扩展即可
|
||||||
|
|
||||||
|
当然,你可以不按这套规则出发,目录结构按自己的舒服的方式去设计,当然也是可以的,不过这得花费一些时间了。
|
||||||
0
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/01.依赖关系.md
Normal file
0
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/01.依赖关系.md
Normal file
BIN
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/image-1.png
Normal file
BIN
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/image-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
BIN
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/image.png
Normal file
BIN
Yi.Doc.Md/01.框架快速开始教程/00.快速上手/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
34
Yi.Doc.Md/01.框架快速开始教程/05.脚手架使用.md
Normal file
34
Yi.Doc.Md/01.框架快速开始教程/05.脚手架使用.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
## 简介
|
||||||
|
上节说到,真正关注的代码其实只用在src中
|
||||||
|

|
||||||
|
当我们要新建一个项目或者模块的时候,并不想取这个`Yi.Abp`的名字,我们可以使用dotnet的脚手架进行模板的生成
|
||||||
|
|
||||||
|
**环境**:只需要dotnet sdk即可
|
||||||
|
|
||||||
|
## 步骤
|
||||||
|

|
||||||
|
在模板文件目录上,有一个`.template.config`文件夹,就是通过这个进行控制模板的生成及替换
|
||||||
|
|
||||||
|
进入该目录,使用cmd执行以以下命令:
|
||||||
|
``` shell
|
||||||
|
dotnet new install . --force
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
出现 `已安装以下模板` 及代表安装完成
|
||||||
|
|
||||||
|
>我们只需要安装一次即可,如果模板文件发生变化,我们生成出来的文件也是一样会变化的
|
||||||
|
|
||||||
|
当模板安装完成,接下来我们可以选择一个自己想要的空白文件夹,输入命令:
|
||||||
|
|
||||||
|
``` shell
|
||||||
|
dotnet new yi --name=Acme.BookStore
|
||||||
|
#Acme.BookStore可以替换成你想要生成的名称即可
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
最后查看目录:
|
||||||
|

|
||||||
|
这个便是我们想要的结果了
|
||||||
@@ -35,15 +35,15 @@ export function getCacheValue(cacheName, cacheKey) {
|
|||||||
// 清理指定名称缓存
|
// 清理指定名称缓存
|
||||||
export function clearCacheName(cacheName) {
|
export function clearCacheName(cacheName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitor/cache/clearCacheName/' + cacheName,
|
url: '/monitor-cache/key/' + cacheName,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理指定键名缓存
|
// 清理指定键名缓存
|
||||||
export function clearCacheKey(cacheKey) {
|
export function clearCacheKey(cacheName,cacheKey) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitor/cache/clearCacheKey/' + cacheKey,
|
url: '/monitor-cache/value/'+cacheName+'/' + cacheKey,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export function clearCacheKey(cacheKey) {
|
|||||||
// 清理全部缓存
|
// 清理全部缓存
|
||||||
export function clearCacheAll() {
|
export function clearCacheAll() {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitor/cache/clearCacheAll',
|
url: '/monitor-cache/clear',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ import request from '@/utils/request'
|
|||||||
// 查询公告列表
|
// 查询公告列表
|
||||||
export function listNotice(query) {
|
export function listNotice(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice/list',
|
url: '/notice',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询公告详细
|
// 查询公告详细
|
||||||
export function getNotice(noticeId) {
|
export function getNotice(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice/' + noticeId,
|
url: `/notice/${id}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -20,26 +20,41 @@ export function getNotice(noticeId) {
|
|||||||
// 新增公告
|
// 新增公告
|
||||||
export function addNotice(data) {
|
export function addNotice(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice',
|
url: '/notice',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改公告
|
// 修改公告
|
||||||
export function updateNotice(data) {
|
export function updateNotice(id,data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice',
|
url: `/notice/${id}`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除公告
|
// 删除公告
|
||||||
export function delNotice(noticeId) {
|
export function delNotice(ids) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice',
|
url: `/notice`,
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
params:{id:noticeId}
|
params:{id:ids}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送在线公告
|
||||||
|
export function sendOnlineNotice(id) {
|
||||||
|
return request({
|
||||||
|
url: '/notice/online/'+id,
|
||||||
|
method: 'post',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 发送离线公告
|
||||||
|
export function sendOfflineNotice(id) {
|
||||||
|
return request({
|
||||||
|
url: '/notice/offline/'+id,
|
||||||
|
method: 'post',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route }">
|
||||||
<transition name="fade-transform" mode="out-in">
|
<transition name="slide-fade" mode="out-in">
|
||||||
<keep-alive :include="tagsViewStore.cachedViews">
|
<keep-alive :include="tagsViewStore.cachedViews">
|
||||||
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
|
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
@@ -19,6 +19,24 @@ const tagsViewStore = useTagsViewStore()
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
/*
|
||||||
|
进入和离开动画可以使用不同
|
||||||
|
持续时间和速度曲线。
|
||||||
|
*/
|
||||||
|
.slide-fade-enter-active {
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-leave-active {
|
||||||
|
transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter-from,
|
||||||
|
.slide-fade-leave-to {
|
||||||
|
transform: translateX(20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.app-main {
|
.app-main {
|
||||||
/* 50= navbar 50 */
|
/* 50= navbar 50 */
|
||||||
min-height: calc(100vh - 50px);
|
min-height: calc(100vh - 50px);
|
||||||
|
|||||||
@@ -374,7 +374,8 @@ const handleCodeToWeb = async () => {
|
|||||||
/** CodeToWeb */
|
/** CodeToWeb */
|
||||||
const handleWebToCode = async () => {
|
const handleWebToCode = async () => {
|
||||||
const response= await webToCode(ids.value);
|
const response= await webToCode(ids.value);
|
||||||
if(response.statusCode==200)
|
console.log(response,"response");
|
||||||
|
if(response.status==200||response.status==204)
|
||||||
{
|
{
|
||||||
proxy.$modal.msgSuccess("代码生成成功");
|
proxy.$modal.msgSuccess("代码生成成功");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ function refreshCacheKeys() {
|
|||||||
|
|
||||||
/** 清理指定键名缓存 */
|
/** 清理指定键名缓存 */
|
||||||
function handleClearCacheKey(cacheKey) {
|
function handleClearCacheKey(cacheKey) {
|
||||||
clearCacheKey(cacheKey).then(response => {
|
clearCacheKey(nowCacheName.value,cacheKey).then(response => {
|
||||||
proxy.$modal.msgSuccess("清理缓存键名[" + cacheKey + "]成功");
|
proxy.$modal.msgSuccess("清理缓存键名[" + cacheKey + "]成功");
|
||||||
getCacheKeys();
|
getCacheKeys();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
<el-form-item label="公告标题" prop="noticeTitle">
|
<el-form-item label="公告标题" prop="title">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.noticeTitle"
|
v-model="queryParams.title"
|
||||||
placeholder="请输入公告标题"
|
placeholder="请输入公告标题"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="handleQuery"
|
@keyup.enter="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="操作人员" prop="createBy">
|
<el-form-item label="类型" prop="type">
|
||||||
<el-input
|
<el-select v-model="queryParams.type" placeholder="公告类型" clearable>
|
||||||
v-model="queryParams.createBy"
|
|
||||||
placeholder="请输入操作人员"
|
|
||||||
clearable
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="类型" prop="noticeType">
|
|
||||||
<el-select v-model="queryParams.noticeType" placeholder="公告类型" clearable>
|
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in sys_notice_type"
|
v-for="dict in sys_notice_type"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
@@ -68,31 +60,47 @@
|
|||||||
|
|
||||||
<el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column label="序号" align="center" prop="noticeId" width="100" />
|
<el-table-column label="序号" align="center" prop="id" width="300" />
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="公告标题"
|
label="公告标题"
|
||||||
align="center"
|
align="center"
|
||||||
prop="noticeTitle"
|
prop="title"
|
||||||
:show-overflow-tooltip="true"
|
:show-overflow-tooltip="true"
|
||||||
/>
|
/>
|
||||||
<el-table-column label="公告类型" align="center" prop="noticeType" width="100">
|
<el-table-column label="公告类型" align="center" prop="type" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_notice_type" :value="scope.row.noticeType" />
|
<dict-tag :options="sys_notice_type" :value="scope.row.type" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
<el-table-column label="状态" align="center" prop="state" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_notice_status" :value="scope.row.status" />
|
<el-tag type="info">{{sys_notice_state.filter(x=>x.value==scope.row.state)[0]?.label}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建者" align="center" prop="createBy" width="100" />
|
<el-table-column label="创建时间" align="center" prop="creationTime" width="100">
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="100">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.creationTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="Promotion"
|
||||||
|
@click="handleOnlineSend(scope.row.id)"
|
||||||
|
v-hasPermi="['system:notice:edit']"
|
||||||
|
>在线发送</el-button>
|
||||||
|
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="Promotion"
|
||||||
|
@click="handleOfflineSend(scope.row.id)"
|
||||||
|
v-hasPermi="['system:notice:edit']"
|
||||||
|
>离线发送</el-button>
|
||||||
|
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
type="text"
|
type="text"
|
||||||
icon="Edit"
|
icon="Edit"
|
||||||
@@ -122,13 +130,13 @@
|
|||||||
<el-form ref="noticeRef" :model="form" :rules="rules" label-width="80px">
|
<el-form ref="noticeRef" :model="form" :rules="rules" label-width="80px">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="公告标题" prop="noticeTitle">
|
<el-form-item label="公告标题" prop="title">
|
||||||
<el-input v-model="form.noticeTitle" placeholder="请输入公告标题" />
|
<el-input v-model="form.title" placeholder="请输入公告标题" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="公告类型" prop="noticeType">
|
<el-form-item label="公告类型" prop="type">
|
||||||
<el-select v-model="form.noticeType" placeholder="请选择">
|
<el-select v-model="form.type" placeholder="请选择">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in sys_notice_type"
|
v-for="dict in sys_notice_type"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
@@ -140,9 +148,9 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<el-radio-group v-model="form.status">
|
<el-radio-group v-model="form.state">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in sys_notice_status"
|
v-for="dict in sys_notice_state"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.value"
|
:label="dict.value"
|
||||||
>{{ dict.label }}</el-radio>
|
>{{ dict.label }}</el-radio>
|
||||||
@@ -155,7 +163,7 @@
|
|||||||
:rows="6"
|
:rows="6"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder="请输入内容"
|
placeholder="请输入内容"
|
||||||
v-model="form.noticeContent"
|
v-model="form.content"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -172,11 +180,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Notice">
|
<script setup name="Notice">
|
||||||
import { listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";
|
import { sendOnlineNotice,sendOfflineNotice,listNotice, getNotice, delNotice, addNotice, updateNotice } from "@/api/system/notice";
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
const { sys_notice_status, sys_notice_type } = proxy.useDict("sys_notice_status", "sys_notice_type");
|
const sys_notice_state=[
|
||||||
|
{label:'启用',value:true},
|
||||||
|
{label:'停用',value:false}
|
||||||
|
];
|
||||||
|
const sys_notice_type=[
|
||||||
|
{label:'走马灯',value:'MerryGoRound'},
|
||||||
|
{label:'提示弹窗',value:'Popup'}
|
||||||
|
];
|
||||||
const noticeList = ref([]);
|
const noticeList = ref([]);
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -192,13 +206,13 @@ const data = reactive({
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
skipCount: 1,
|
skipCount: 1,
|
||||||
maxResultCount: 10,
|
maxResultCount: 10,
|
||||||
noticeTitle: undefined,
|
title: undefined,
|
||||||
createBy: undefined,
|
createBy: undefined,
|
||||||
status: undefined
|
state: undefined
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
noticeTitle: [{ required: true, message: "公告标题不能为空", trigger: "blur" }],
|
title: [{ required: true, message: "公告标题不能为空", trigger: "blur" }],
|
||||||
noticeType: [{ required: true, message: "公告类型不能为空", trigger: "change" }]
|
type: [{ required: true, message: "公告类型不能为空", trigger: "change" }]
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -208,8 +222,8 @@ const { queryParams, form, rules } = toRefs(data);
|
|||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
listNotice(queryParams.value).then(response => {
|
listNotice(queryParams.value).then(response => {
|
||||||
noticeList.value = response.rows;
|
noticeList.value = response.data.items;
|
||||||
total.value = response.total;
|
total.value = response.data.totalCount;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -221,11 +235,11 @@ function cancel() {
|
|||||||
/** 表单重置 */
|
/** 表单重置 */
|
||||||
function reset() {
|
function reset() {
|
||||||
form.value = {
|
form.value = {
|
||||||
noticeId: undefined,
|
id: undefined,
|
||||||
noticeTitle: undefined,
|
title: undefined,
|
||||||
noticeType: undefined,
|
type: undefined,
|
||||||
noticeContent: undefined,
|
content: undefined,
|
||||||
status: "0"
|
state: true
|
||||||
};
|
};
|
||||||
proxy.resetForm("noticeRef");
|
proxy.resetForm("noticeRef");
|
||||||
}
|
}
|
||||||
@@ -241,7 +255,7 @@ function resetQuery() {
|
|||||||
}
|
}
|
||||||
/** 多选框选中数据 */
|
/** 多选框选中数据 */
|
||||||
function handleSelectionChange(selection) {
|
function handleSelectionChange(selection) {
|
||||||
ids.value = selection.map(item => item.noticeId);
|
ids.value = selection.map(item => item.id);
|
||||||
single.value = selection.length != 1;
|
single.value = selection.length != 1;
|
||||||
multiple.value = !selection.length;
|
multiple.value = !selection.length;
|
||||||
}
|
}
|
||||||
@@ -254,8 +268,8 @@ function handleAdd() {
|
|||||||
/**修改按钮操作 */
|
/**修改按钮操作 */
|
||||||
function handleUpdate(row) {
|
function handleUpdate(row) {
|
||||||
reset();
|
reset();
|
||||||
const noticeId = row.noticeId || ids.value;
|
const id = row.id || ids.value;
|
||||||
getNotice(noticeId).then(response => {
|
getNotice(id).then(response => {
|
||||||
form.value = response.data;
|
form.value = response.data;
|
||||||
open.value = true;
|
open.value = true;
|
||||||
title.value = "修改公告";
|
title.value = "修改公告";
|
||||||
@@ -265,12 +279,13 @@ function handleUpdate(row) {
|
|||||||
function submitForm() {
|
function submitForm() {
|
||||||
proxy.$refs["noticeRef"].validate(valid => {
|
proxy.$refs["noticeRef"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (form.value.noticeId != undefined) {
|
if (form.value.id != undefined) {
|
||||||
updateNotice(form.value).then(response => {
|
updateNotice(form.value.id,form.value).then(response => {
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
addNotice(form.value).then(response => {
|
addNotice(form.value).then(response => {
|
||||||
proxy.$modal.msgSuccess("新增成功");
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
@@ -283,14 +298,23 @@ function submitForm() {
|
|||||||
}
|
}
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
function handleDelete(row) {
|
function handleDelete(row) {
|
||||||
const noticeIds = row.noticeId || ids.value
|
const ids2 = row.id || ids.value
|
||||||
proxy.$modal.confirm('是否确认删除公告编号为"' + noticeIds + '"的数据项?').then(function() {
|
proxy.$modal.confirm('是否确认删除公告编号为"' + ids2 + '"的数据项?').then(function() {
|
||||||
return delNotice(noticeIds);
|
return delNotice(ids2);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
getList();
|
getList();
|
||||||
proxy.$modal.msgSuccess("删除成功");
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleOnlineSend=async (id)=>{
|
||||||
|
await sendOnlineNotice(id);
|
||||||
|
proxy.$modal.msgSuccess("在线消息发送成功");
|
||||||
|
|
||||||
|
}
|
||||||
|
const handleOfflineSend=async (id)=>{
|
||||||
|
await sendOfflineNotice(id);
|
||||||
|
proxy.$modal.msgSuccess("离线消息发送成功");
|
||||||
|
}
|
||||||
getList();
|
getList();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -211,11 +211,11 @@ const deptRef = ref(null);
|
|||||||
|
|
||||||
/** 数据范围选项*/
|
/** 数据范围选项*/
|
||||||
const dataScopeOptions = ref([
|
const dataScopeOptions = ref([
|
||||||
{ value: 0, label: "全部数据权限" },
|
{ value: 'ALL', label: "全部数据权限" },
|
||||||
{ value: 1, label: "自定数据权限" },
|
{ value: 'CUSTOM', label: "自定数据权限" },
|
||||||
{ value: 2, label: "本部门数据权限" },
|
{ value: 'DEPT', label: "本部门数据权限" },
|
||||||
{ value: 3, label: "本部门及以下数据权限" },
|
{ value: 'DEPT_FOLLOW', label: "本部门及以下数据权限" },
|
||||||
{ value: 4, label: "仅本人数据权限" },
|
{ value: 'USER', label: "仅本人数据权限" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
|
|||||||
Reference in New Issue
Block a user