😎清理代码及优化其他细节

This commit is contained in:
zuohuaijun 2025-08-28 00:19:30 +08:00
parent 65ec0e551b
commit efe5388be1
58 changed files with 219 additions and 184 deletions

View File

@ -12,7 +12,6 @@
"EventBus": {
// Redis
"EventSourceType": "Memory", // MemoryRedisRabbitMQKafka
"Kafka": {
}
}

View File

@ -22,5 +22,5 @@ global using System;
global using System.Collections.Generic;
global using System.ComponentModel;
global using System.ComponentModel.DataAnnotations;
global using System.Threading.Tasks;
global using System.Linq;
global using System.Linq;
global using System.Threading.Tasks;

View File

@ -5,6 +5,7 @@
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Application;
public class RabbitMqHandler : IMessageHandler
{
public string QueueName => "admin.net.rabbitmq";//队列名称
@ -12,7 +13,7 @@ public class RabbitMqHandler : IMessageHandler
//消息处理函数
public async Task HandleMessageAsync(string message)
{
//Todo
//Todo
Console.WriteLine(message);
await Task.CompletedTask;

View File

@ -5,7 +5,6 @@
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Plugin.WorkWeixin;
using AngleSharp.Dom;
using Furion.Localization;
using Furion.Logging;
using Microsoft.Extensions.Logging;
@ -31,7 +30,6 @@ public class TestService : IDynamicApiController
_workWxUserService = workWxUserService;
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName); // 日志过滤标识(会写入数据库)
_producer = producer;
}
[HttpGet("helloWord")]
@ -99,7 +97,6 @@ public class TestService : IDynamicApiController
[ApiDescriptionSettings(Name = "SendMessageToRabbitMQ", Description = "测试")]
public async Task SendMessageToRabbitMQ([FromQuery] string input)
{
await _producer.SendMessage("admin.net.rabbitmq",$"Hello {input}!");
await _producer.SendMessage("admin.net.rabbitmq", $"Hello {input}!");
}
}

View File

@ -27,15 +27,15 @@
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" Aliases="BouncyCastleV2" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.1.4" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.110" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.110" />
<PackageReference Include="Furion.Pure" Version="4.9.7.110" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.1.5" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.112" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.112" />
<PackageReference Include="Furion.Pure" Version="4.9.7.112" />
<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
<PackageReference Include="Hashids.net" Version="1.7.0" />
<PackageReference Include="IPTools.China" Version="1.6.0" />
<PackageReference Include="IPTools.International" Version="1.6.0" />
<PackageReference Include="log4net" Version="3.1.0" />
<PackageReference Include="log4net" Version="3.2.0" />
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.6" />
<PackageReference Include="Magicodes.IE.Pdf" Version="2.7.6" />
<PackageReference Include="Magicodes.IE.Word" Version="2.7.6" />
@ -52,23 +52,23 @@
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.11.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.13.0" />
<PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.248" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.199" />
<PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.253" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.200" />
<PackageReference Include="SSH.NET" Version="2025.0.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.7" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1273" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
<PackageReference Include="microsoft.semantickernel" Version="1.62.0" />
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.62.0" />
<PackageReference Include="microsoft.semantickernel" Version="1.63.0" />
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.63.0" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Amazon" Version="1.56.0-alpha" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.54.0-alpha" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.HuggingFace" Version="1.56.0-preview" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.54.0-alpha" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Qdrant" Version="1.54.0-preview" />
<PackageReference Include="Microsoft.SemanticKernel.PromptTemplates.Handlebars" Version="1.62.0" />
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.62.0" />
<PackageReference Include="Microsoft.SemanticKernel.PromptTemplates.Handlebars" Version="1.63.0" />
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.63.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">

View File

@ -125,7 +125,7 @@ public class DateTimeRangeAttribute : ValidationAttribute
/// </summary>
private string NowString => NowProvider().ToString("yyyy-MM-dd HH:mm:ss");
/// <summary>
/// <summary>
/// 执行验证逻辑
/// </summary>
protected override ValidationResult IsValid(object? value, ValidationContext validationContext)

View File

@ -42,5 +42,4 @@ public class CommonConst
/// 远程请求请求头参数键值前缀
/// </summary>
public const string HttpRemoteHeaderKeyPrefix = "__HTTP_CLIENT_";
}

View File

@ -69,7 +69,6 @@ public partial class SysDictType : EntityBase
[SugarColumn(ColumnDescription = "是否是枚举转换字典", DefaultValue = "2")]
public virtual YesNoEnum IsEnum { get; set; } = YesNoEnum.N;
/// <summary>
/// 字典值集合
/// </summary>

View File

@ -132,5 +132,4 @@ public partial class SysLogVis : EntityTenantId
/// </summary>
[SugarColumn(ColumnDescription = "创建者姓名", Length = 64, IsOnlyIgnoreUpdate = true)]
public virtual string? CreateUserName { get; set; }
}

View File

@ -9,7 +9,8 @@ namespace Admin.NET.Core;
/// <summary>
/// Http远程服务扩展
/// </summary>
public static class HttpRemotesExtension {
public static class HttpRemotesExtension
{
/// <summary>
/// 添加Http远程服务
/// </summary>
@ -28,7 +29,8 @@ public static class HttpRemotesExtension {
foreach (var kv in opt.Headers) client.DefaultRequestHeaders.Add(kv.Key, kv.Value);
})
.AddHttpMessageHandler<HttpLoggingHandler>()
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler {
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
UseCookies = opt.UseCookies
});
}

View File

@ -4,8 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Furion.Shapeless;
namespace Admin.NET.Core;
/// <summary>

View File

@ -8,7 +8,6 @@ using System.Net.Http.Headers;
namespace Admin.NET.Core;
/// <summary>
/// http日志处理
/// </summary>
@ -132,8 +131,8 @@ public class HttpLoggingHandler : DelegatingHandler, ITransient
/// <returns></returns>
public static HttpRequestBuilder SetRemoteApiAttr(HttpRequestBuilder builder, string httpName, HttpRemoteApiAttribute attr)
{
builder.WithHeader(IgnoreLogKey, attr.IgnoreLog, replace:true);
builder.WithHeader(ApiDescKey, attr.Desc, replace:true);
builder.WithHeader(IgnoreLogKey, attr.IgnoreLog, replace: true);
builder.WithHeader(ApiDescKey, attr.Desc, replace: true);
builder.SetHttpClientName(httpName);
return builder;
}

View File

@ -4,9 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Furion.ConfigurableOptions;
namespace Admin.NET.Application;
namespace Admin.NET.Core;
/// <summary>
/// 远程请求配置

View File

@ -3,9 +3,12 @@
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
public interface IMessageHandler
{
string QueueName { get; }
Task HandleMessageAsync(string message);
}

View File

@ -3,7 +3,9 @@
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
public static class RabbitMQExtention
{
/// <summary>

View File

@ -7,6 +7,7 @@
using RabbitMQ.Client;
namespace Admin.NET.Core;
public class RabbitMqConnection
{
private IConnection _connection;
@ -31,12 +32,11 @@ public class RabbitMqConnection
_channel = await _connection.CreateChannelAsync();
return true;
}
catch(Exception ex)
catch (Exception ex)
{
Console.WriteLine($"RabbitMQ 连接失败: {ex.Message}");
return false;
}
}
public void Dispose()
@ -44,4 +44,4 @@ public class RabbitMqConnection
_channel?.Dispose();
_connection?.Dispose();
}
}
}

View File

@ -3,10 +3,12 @@
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
namespace Admin.NET.Core;
public class RabbitMqConsumer : BackgroundService
{
private readonly RabbitMqConnection _connection;
@ -19,6 +21,7 @@ public class RabbitMqConsumer : BackgroundService
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName); // 日志过滤标识(会写入数据库)
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
if (!await _connection.TryConnectAsync())
@ -67,4 +70,4 @@ public class RabbitMqConsumer : BackgroundService
_connection.Dispose();
});
}
}
}

View File

@ -5,7 +5,8 @@
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
public class RabbitMqOptions : IConfigurableOptions
public class RabbitMqOptions : IConfigurableOptions
{
/// <summary>
/// 账号
@ -31,4 +32,4 @@ public class RabbitMqOptions : IConfigurableOptions
/// 虚拟主机
/// </summary>
public string VirtualHost { get; set; } = "/";
}
}

View File

@ -7,6 +7,7 @@
using RabbitMQ.Client;
namespace Admin.NET.Core;
public class RabbitMqProducer
{
private readonly RabbitMqConnection _connection;
@ -27,4 +28,4 @@ public class RabbitMqProducer
var body = Encoding.UTF8.GetBytes(message);
await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queueName, mandatory: true, basicProperties: properties, body: body);
}
}
}

View File

@ -21,10 +21,10 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
return
[
new SysOrg{ Id=SqlSugarConst.DefaultTenantId, Pid=0, Name="系统默认", Code="1001", Type="101", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统默认", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 1, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 2, Pid=SqlSugarConst.DefaultTenantId, Name="开发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="开发部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 3, Pid=SqlSugarConst.DefaultTenantId, Name="售后部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="售后部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 4, Pid=SqlSugarConst.DefaultTenantId, Name="其他", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 10, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 20, Pid=SqlSugarConst.DefaultTenantId, Name="开发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="开发部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 30, Pid=SqlSugarConst.DefaultTenantId, Name="售后部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="售后部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 40, Pid=SqlSugarConst.DefaultTenantId, Name="其他", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
];
}
}

View File

@ -20,13 +20,13 @@ public class SysPosSeedData : ISqlSugarEntitySeedData<SysPos>
{
return
[
new SysPos{ Id=1300000000101, Name="党委书记", Code="dwsj", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="党委书记", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000102, Name="局长", Code="jz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="局长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000103, Name="副局长", Code="fjz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副局长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000104, Name="科长", Code="kz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="科长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000105, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000106, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=1300000000107, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId, Name="党委书记", Code="dwsj", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="党委书记", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 10, Name="局长", Code="jz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="局长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 20, Name="副局长", Code="fjz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副局长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 30, Name="科长", Code="kz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="科长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 40, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 50, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=SqlSugarConst.DefaultTenantId },
new SysPos{ Id=SqlSugarConst.DefaultTenantId + 60, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
];
}
}

View File

@ -26,6 +26,11 @@ public class PageDictDataInput : BasePageInput
/// 编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 值
/// </summary>
public string Value { get; set; }
}
public class AddDictDataInput : SysDictData

View File

@ -35,6 +35,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
{
return await _sysDictDataRep.AsQueryable()
.Where(u => u.DictTypeId == input.DictTypeId)
.WhereIF(!string.IsNullOrEmpty(input.Value?.Trim()), u => u.Code.Contains(input.Value))
.WhereIF(!string.IsNullOrEmpty(input.Code?.Trim()), u => u.Code.Contains(input.Code))
.WhereIF(!string.IsNullOrEmpty(input.Label?.Trim()), u => u.Label.Contains(input.Label))
.OrderBy(u => new { u.OrderNo, u.Code })

View File

@ -100,7 +100,6 @@ public class PageLogHttpOutput
/// 创建用户
/// </summary>
public string CreateUserName { get; set; }
}
/// <summary>

View File

@ -85,6 +85,7 @@ public class SysUserService : IDynamicApiController, ITransient
.WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
.WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName))
.WhereIF(!string.IsNullOrWhiteSpace(input.Phone), u => u.Phone.Contains(input.Phone))
.WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Account.Contains(input.Keyword) || u.RealName.Contains(input.Keyword) || u.Phone.Contains(input.Keyword) || u.JobNum.Contains(input.Keyword))
.OrderBy(u => new { u.OrderNo, u.Id })
.Select((u, a, b) => new UserOutput
{

View File

@ -9,7 +9,7 @@ namespace Admin.NET.Core;
/// <summary>
/// 当前登录用户信息
/// </summary>
public class UserManager (
public class UserManager(
SysCacheService sysCacheService,
IHttpContextAccessor httpContextAccessor) : UserSessionDao, IScoped
{

View File

@ -17,7 +17,6 @@ public class SysWechatService : IDynamicApiController, ITransient
private readonly WechatApiClient _wechatApiClient;
private readonly SysAuthService _sysAuthService;
public SysWechatService(
UserManager userManager,
SysAuthService sysAuthService,

View File

@ -6,7 +6,6 @@
using NewLife.IO;
using NewLife.Reflection;
using SixLabors.ImageSharp.Processing;
using System.Text.Json;
namespace Admin.NET.Core;

View File

@ -295,7 +295,7 @@ public static class SqlSugarSetup
};
// 超管不受任何过滤器限制
if (userManager.Value.AccountType == AccountTypeEnum.SuperAdmin)return;
if (userManager.Value.AccountType == AccountTypeEnum.SuperAdmin) return;
// 配置假删除过滤器
dbProvider.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDelete == false);

View File

@ -4,12 +4,12 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System;
using System.Linq;
using System.Reflection;
using Furion;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System;
using System.Linq;
using System.Reflection;
namespace Admin.NET.Web.Core;

View File

@ -4,13 +4,13 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
namespace Admin.NET.Web.Core;

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Application;
using Admin.NET.Core;
using AspNetCoreRateLimit;
using Furion;

View File

@ -33,8 +33,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
@ -88,7 +86,7 @@ public class Startup : AppStartup
services.AddTaskQueue(builder =>
{
builder.NumRetries = 0; // 默认重试 0 次
//builder.RetryTimeout = 1000; // 每次重试间隔 1000ms
//builder.RetryTimeout = 1000; // 每次重试间隔 1000ms
// 订阅 TaskQueue 意外未捕获异常
builder.UnobservedTaskExceptionHandler = (obj, args) =>
@ -148,6 +146,7 @@ public class Startup : AppStartup
// NewtonsoftJson 序列化设置
static void SetNewtonsoftJsonSetting(JsonSerializerSettings setting)
{
setting.DateTimeZoneHandling = DateTimeZoneHandling.Local;
//setting.ContractResolver = new DefaultContractResolver(); // 序列化属性名大写(属性原样输出)
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
//setting.Converters.AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss", localized: true); // 时间格式化

View File

@ -5,7 +5,6 @@
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Furion.DataEncryption;
using Furion.JsonSerialization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
@ -19,6 +18,7 @@ namespace Admin.NET.Plugin.ReZero.Service;
public class SuperApiAop : DefaultSuperApiAop
{
private static readonly Lazy<UserManager> _userManager = new(() => App.GetService<UserManager>());
public override async Task OnExecutingAsync(InterfaceContext aopContext)
{
////if (aopContext.InterfaceType == InterfaceType.DynamicApi)

View File

@ -8,11 +8,6 @@ global using Admin.NET.Core;
global using Admin.NET.Core.Service;
global using Furion;
global using Furion.DependencyInjection;
global using Furion.EventBus;
global using Furion.HttpRemote;
global using Lazy.Captcha.Core;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Mvc;
global using Newtonsoft.Json;
global using System.ComponentModel.DataAnnotations;
global using System.Text.Json.Serialization;
global using System.ComponentModel.DataAnnotations;

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.WorkWeixin;
/// <summary>

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.WorkWeixin;
/// <summary>

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.WorkWeixin;
/// <summary>
@ -39,7 +38,7 @@ public class WorkWxTagService(WorkWxBaseService baseService) : ITransient
/// <returns></returns>
public async Task<BaseWorkWxOutput> Delete(long id)
{
return await baseService.SendAsync<DeleteTagWorkWxInput, BaseWorkWxOutput>(new(){ TagId = id });
return await baseService.SendAsync<DeleteTagWorkWxInput, BaseWorkWxOutput>(new() { TagId = id });
}
/// <summary>
@ -49,7 +48,7 @@ public class WorkWxTagService(WorkWxBaseService baseService) : ITransient
/// <returns></returns>
public async Task<TagMembersWorkWxOutput> Get(long id)
{
return await baseService.SendAsync<TagMembersWorkWxInput, TagMembersWorkWxOutput>(new(){ TagId = id });
return await baseService.SendAsync<TagMembersWorkWxInput, TagMembersWorkWxOutput>(new() { TagId = id });
}
/// <summary>

View File

@ -786,7 +786,7 @@ public class JoinQrcodeWorkWxOutput : BaseWorkWxOutput
{
get
{
if (string.IsNullOrEmpty(JoinQrcode))return null;
if (string.IsNullOrEmpty(JoinQrcode)) return null;
var match = Regex.Match(JoinQrcode, @"qr_size=(\d)");
return match.Success ? int.Parse(match.Groups[1].Value) : null;
}

View File

@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.WorkWeixin;
/// <summary>
@ -150,7 +149,7 @@ public class WorkWxUserService(WorkWxBaseService baseService) : ITransient
/// <returns></returns>
public async Task<UserIdWorkWxOutput> GetUserIdByEmail(string email, int? emailType = 1)
{
return await baseService.SendAsync<UserIdByEmailWorkWxInput, UserIdWorkWxOutput>(new(){ Email = email, EmailType = emailType });
return await baseService.SendAsync<UserIdByEmailWorkWxInput, UserIdWorkWxOutput>(new() { Email = email, EmailType = emailType });
}
/// <summary>
@ -161,6 +160,6 @@ public class WorkWxUserService(WorkWxBaseService baseService) : ITransient
/// <returns></returns>
public async Task<UserIdListWorkWxOutput> GetUserIdList(string cursor = null, int? limit = 20)
{
return await baseService.SendAsync<UserIdListWorkWxInput, UserIdListWorkWxOutput>(new(){ Cursor = cursor, Limit = limit });
return await baseService.SendAsync<UserIdListWorkWxInput, UserIdListWorkWxOutput>(new() { Cursor = cursor, Limit = limit });
}
}

View File

@ -4,14 +4,12 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System.Reflection;
using System.Text;
using Admin.NET.Plugin.WorkWeixin.Const;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.Logging;
using Microsoft.Extensions.Options;
using System.Reflection;
using System.Text;
namespace Admin.NET.Plugin.WorkWeixin;

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2025.08.19",
"lastBuildTime": "2025.08.28",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -26,7 +26,7 @@
"@vue-office/docx": "^1.6.3",
"@vue-office/excel": "^1.7.14",
"@vue-office/pdf": "^2.0.10",
"@vueuse/core": "^13.7.0",
"@vueuse/core": "^13.8.0",
"@vxe-ui/plugin-export-xlsx": "^4.3.0",
"@vxe-ui/plugin-render-element": "^4.1.0",
"@wangeditor/editor": "^5.1.23",
@ -39,7 +39,7 @@
"cropperjs": "^1.6.2",
"crypto-js": "^4.2.0",
"echarts": "^6.0.0",
"element-plus": "^2.10.7",
"element-plus": "^2.11.1",
"exceljs": "^4.4.0",
"flag-icons": "^7.5.0",
"franc": "^6.2.0",
@ -48,7 +48,7 @@
"json-editor-vue": "^0.18.1",
"jsplumb": "^2.15.6",
"lodash-es": "^4.17.21",
"magic-string": "^0.30.17",
"magic-string": "^0.30.18",
"md-editor-v3": "^5.8.4",
"mitt": "^3.0.1",
"monaco-editor": "^0.52.2",
@ -69,7 +69,7 @@
"uuid": "^11.1.0",
"vcrontab-3": "^3.3.22",
"vform3-builds": "^3.0.10",
"vue": "^3.5.18",
"vue": "^3.5.20",
"vue-clipboard3": "^2.0.0",
"vue-demi": "0.14.10",
"vue-draggable-plus": "^0.6.0",
@ -81,8 +81,8 @@
"vue-router": "^4.5.1",
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.8.22",
"vxe-table": "^4.15.10",
"vxe-pc-ui": "^4.9.5",
"vxe-table": "^4.16.1",
"xe-utils": "^3.7.8",
"xlsx-js-style": "^1.2.0"
},
@ -90,25 +90,25 @@
"@iconify/vue": "^5.0.0",
"@plugin-web-update-notification/vite": "^2.0.1",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.17.2",
"@types/node": "^22.18.0",
"@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.40.0",
"@typescript-eslint/parser": "^8.40.0",
"@typescript-eslint/eslint-plugin": "^8.41.0",
"@typescript-eslint/parser": "^8.41.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^5.0.1",
"@vue/compiler-sfc": "^3.5.18",
"@vitejs/plugin-vue-jsx": "^5.1.0",
"@vue/compiler-sfc": "^3.5.20",
"cli-progress": "^3.12.0",
"code-inspector-plugin": "^1.2.2",
"code-inspector-plugin": "^1.2.6",
"colors": "^1.4.0",
"dotenv": "^17.2.1",
"eslint": "^9.33.0",
"eslint": "^9.34.0",
"eslint-plugin-vue": "^10.4.0",
"globals": "^16.3.0",
"less": "^4.4.1",
"prettier": "^3.6.2",
"rollup-plugin-visualizer": "^6.0.3",
"sass": "^1.90.0",
"sass": "^1.91.0",
"terser": "^5.43.1",
"typescript": "^5.9.2",
"vite": "^7.1.3",

View File

@ -105,4 +105,12 @@ export interface PageDictDataInput {
* @memberof PageDictDataInput
*/
code?: string | null;
/**
*
*
* @type {string}
* @memberof PageDictDataInput
*/
value?: string | null;
}

View File

@ -67,7 +67,7 @@ const props = defineProps({
* @example [5, -2]
*/
offset: {
type: (Array as unknown) as PropType<[number, number]>,
type: Array as unknown as PropType<[number, number]>,
default: [5, -2] as const,
},
/**
@ -87,25 +87,32 @@ const state = reactive({
data: props.data,
});
watch(() => state.active, (newValue) => {
emit('update:modelValue', newValue);
emit('change', newValue, state.data);
}, { immediate: true })
watch(() => props.data, (newValue) => {
state.data = newValue ?? [];
console.log(state.data);
}, { immediate: true })
watch(
() => state.active,
(newValue) => {
emit('update:modelValue', newValue);
emit('change', newValue, state.data);
},
{ immediate: true }
);
watch(
() => props.data,
(newValue) => {
state.data = newValue ?? [];
console.log(state.data);
},
{ immediate: true }
);
</script>
<template>
<el-tabs v-model="state.active" class="ml5 mt5" v-bind="$attrs">
<el-tab-pane v-for="(item, index) in state.data" :key="index" :label="item.label" :name="item.value" :disabled="item.disabled" v-show="item.visible === undefined || item.visible">
<template #label v-if="(props.hideZero && item.count || !props.hideZero)">
<template #label v-if="(props.hideZero && item.count) || !props.hideZero">
<el-badge :value="item.count ?? 0" :max="props.max" :offset="props.offset">{{ item.label }}</el-badge>
</template>
</el-tab-pane>
<slot></slot>
</el-tabs>
</template>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

View File

@ -15,18 +15,20 @@
<p class="tip">账号列表</p>
<div style="margin-top: 10px">
<el-form :model="state.queryParams" ref="queryRef" :inline="true">
<el-form-item label="账号名称">
<el-input v-model="state.queryParams.account" placeholder="请输入账号名称" clearable style="width: 150px" @keyup.enter="handleQuery" />
<el-form-item label="关键字">
<el-input v-model="state.queryParams.keyword" clearable style="width: 150px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleQuery"> 查询 </el-button>
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
</el-button-group>
<el-button type="primary" icon="ele-DArrowRight" plain style="margin-left: 10px" @click="handleSelectAllUser"> 全选 </el-button>
</el-form-item>
</el-form>
<el-card class="full-table" shadow="hover">
<el-table ref="refTable" :data="userList" style="height: calc(60vh - 96px)">
<el-table ref="refTable" :data="userList" style="height: calc(70vh - 96px)">
<el-table-column label="操作" width="60" align="center">
<template #default="scope">
<el-button link type="primary" @click="handleSelectUser(scope.row)">
@ -37,6 +39,8 @@
<el-table-column label="账号名称" prop="account" align="center" :show-overflow-tooltip="true" />
<el-table-column label="真实姓名" prop="realName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="联系方式" prop="phone" align="center" :show-overflow-tooltip="true" />
<el-table-column label="岗位" prop="posName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="工号" prop="jobNum" align="center" :show-overflow-tooltip="true" />
<el-table-column label="所属机构" prop="orgName" align="center" :show-overflow-tooltip="true" />
</el-table>
@ -66,6 +70,7 @@
</el-table-column>
<el-table-column label="账号名称" prop="account" :show-overflow-tooltip="true" />
<el-table-column label="真实姓名" prop="realName" :show-overflow-tooltip="true" />
<el-table-column label="工号" prop="jobNum" align="center" :show-overflow-tooltip="true" />
</el-table>
</el-col>
</el-row>
@ -166,16 +171,13 @@ async function handleQuery() {
//
function handleSelectUser(row: { id: string }) {
if (!row || row.id == '') {
ElMessage.error('请选择账号');
return;
}
if (checkedUsersList.value.some((c: { id: any }) => c.id == row.id)) {
ElMessage.error('账号已被选中');
} else {
if (!row || row.id == '') return;
if (!checkedUsersList.value.some((c: { id: any }) => c.id == row.id)) {
checkedUsersList.value.push(row);
}
}
//
function handleRemove(row: { id: any }) {
if (checkedUsersList.value.some((c: { id: any }) => c.id == row.id)) {
@ -185,6 +187,17 @@ function handleRemove(row: { id: any }) {
}
}
//
function handleSelectAllUser() {
if (userList == null || userList.value.length < 1) return;
userList.value.forEach((item: any) => {
if (!checkedUsersList.value.some((c: { id: any }) => c.id == item.id)) {
checkedUsersList.value.push(item);
}
});
}
// /
let saveDialog = () => {
let checkedList = [...checkedUsersList.value].map((item) => ({

View File

@ -296,7 +296,7 @@ const getDataList = (): DictItem[] => {
return data.map((item: any) => ({
...item,
label: item[props.propLabel] ?? [item.name, item.desc].filter(x => x).join("-"),
label: item[props.propLabel] ?? [item.name, item.desc].filter((x) => x).join('-'),
value: item[props.propValue] ?? item.code,
}));
} catch (error) {
@ -491,12 +491,12 @@ const validateInitialValue = () => {
return new Promise((resolve, reject) => {
if (props.renderAs === 'tag' || !state.value) return resolve(undefined);
if (Array.isArray(state.value)) {
const errorValues = state.value.filter(val => state.dictData.find(e => e[props.propValue] == val) === undefined);
const errorValues = state.value.filter((val) => state.dictData.find((e) => e[props.propValue] == val) === undefined);
if (errorValues && errorValues.length > 0) {
reject(`[g-sys-dict] 未匹配到选项值:${JSON.stringify(errorValues)}`);
}
} else if (state.value) {
if (!state.dictData.find(e => e[props.propValue] === state.value)) {
if (!state.dictData.find((e) => e[props.propValue] === state.value)) {
reject(`[g-sys-dict] 未匹配到选项值:${state.value}`);
}
}
@ -515,10 +515,13 @@ const state = reactive({
});
//
watch(() => props.modelValue, (newValue) => {
state.value = parseMultipleValue(newValue);
validateInitialValue();
});
watch(
() => props.modelValue,
(newValue) => {
state.value = parseMultipleValue(newValue);
validateInitialValue();
}
);
watch(() => [userStore.dictList, userStore.constList, state], initData, { immediate: true });
</script>
@ -569,4 +572,4 @@ watch(() => [userStore.dictList, userStore.constList, state], initData, { immedi
</el-radio-button>
</el-radio-group>
</template>
<style scoped lang="scss"></style>
<style scoped lang="scss"></style>

View File

@ -85,6 +85,7 @@ export default {
account: 'Account',
realName: 'Real Name',
jobTitle: 'Job Title',
jobNumb: 'Job Number',
phoneNumber: 'Phone Number',
resetPassword: 'Reset',
unlockAccount: 'Unlock',

View File

@ -87,6 +87,7 @@ export default {
pinyin: '簡拼',
allPinyin: '全拼',
jobTitle: '职位名称',
jobNumb: '工号',
phoneNumber: '手机号码',
resetPassword: '重置密码',
unlockAccount: '解除锁定',

View File

@ -116,10 +116,8 @@ import { useRoutesList } from '/@/stores/routesList';
import other from '/@/utils/other';
import mittBus from '/@/utils/mitt';
import { Local, Session } from '/@/utils/storage';
import { decryptJWT } from '/@/utils/request';
import Push from 'push.js';
import { signalR } from '/@/views/system/onlineUser/signalR';
//
import { languageList, getCountryCode } from '/@/i18n';
import '/node_modules/flag-icons/css/flag-icons.min.css';
@ -346,8 +344,7 @@ const receiveNotice = (msg: any) => {
//
const changePassword = async () => {
//
let userToken = decryptJWT(Local.get('access-token'));
if (userToken.AccountType == 999) return;
if (userInfos.value.accountType == 999) return;
//
var enabledForceChangePassword = themeConfig.value.forceChangePassword ?? true;

View File

@ -69,16 +69,21 @@
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParamsDictData" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-col class="mb5" :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
<el-form-item label="字典值" prop="value">
<el-input v-model="state.queryParamsDictData.value" placeholder="字典值" clearable @keyup.enter.native="handleQueryDictData(true)" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-col class="mb5" :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
<el-form-item label="编码" prop="code">
<el-input v-model="state.queryParamsDictData.code" placeholder="编码" clearable @keyup.enter.native="handleQueryDictData(true)" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
<el-form-item label="文本" prop="code">
<el-input v-model="state.queryParamsDictData.label" placeholder="文本" clearable @keyup.enter.native="handleQueryDictData(true)" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
@ -169,6 +174,7 @@ const state = reactive({
dictTypeId: undefined,
value: undefined,
code: undefined,
label: undefined,
},
localPageParamDictType: {
pageSize: 50 as number,
@ -344,6 +350,7 @@ const handleQueryDictData = async (reset = false) => {
const resetQueryDictData = async () => {
state.queryParamsDictData.value = undefined;
state.queryParamsDictData.code = undefined;
state.queryParamsDictData.label = undefined;
await xGridDictData.value?.commitProxy('reload');
};

View File

@ -19,11 +19,12 @@
<el-form-item label="请求地址">
{{ data.requestUrl?.indexOf('?') == -1 ? data.requestUrl : data.requestUrl?.substring(0, data.requestUrl.indexOf('?')) }}
</el-form-item>
<el-form-item label="Query参数" v-if="data.requestUrl?.indexOf('?') != -1">
<el-row v-for="(value, key, index) in queryObject">
<span class="query-key">{{ key }}</span> = <span class="query-value">{{ value }}</span>&
</el-row>
</el-form-item>
<el-form-item label="Query参数" v-if="data.requestUrl?.indexOf('?') != -1">
<el-row v-for="(value, key, index) in queryObject">
<span class="query-key">{{ key }}</span> = <span class="query-value">{{ value }}</span
>&
</el-row>
</el-form-item>
<el-form-item label="请求头">
<vue-json-pretty :data="data.requestHeaders" showLength showIcon showLineNumber showSelectController />
</el-form-item>
@ -50,17 +51,19 @@
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed} from 'vue';
import { ref, reactive, computed } from 'vue';
import { StringToObj } from '/@/utils/json-utils';
import { SysLogHttp } from '/@/api-services/system/models';
import VueJsonPretty from 'vue-json-pretty';
const data = ref<SysLogHttp>({});
const state = reactive({
visible: false,
selectedTabName: '0',
});
const data = ref<SysLogHttp>({});
const openDialog = (row: any) => {
state.visible = true;
state.selectedTabName = '0';
@ -74,10 +77,12 @@ const openDialog = (row: any) => {
};
const queryObject = computed(() => Object.fromEntries(new URLSearchParams(new URL(data.value?.requestUrl ?? '').search)) ?? {});
defineExpose({
openDialog,
});
</script>
<style lang="less" scoped>
.query-value {
color: #13ce66;
@ -85,4 +90,4 @@ defineExpose({
.query-key {
color: #d55fde;
}
</style>
</style>

View File

@ -3,6 +3,7 @@
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px' }">
<scEcharts v-if="echartsOption.series.data" height="200px" :option="echartsOption" @clickData="clickData"></scEcharts>
</el-card>
<el-card shadow="hover" :body-style="{ padding: '5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
@ -93,7 +94,7 @@
<g-sys-dict v-model="row.isSuccessStatusCode" :code="'YesNoEnum'" />
</template>
<template #row_requestUrl="{ row, $index }">
<el-button v-if="row.requestUrl" class="ml5" icon="ele-CopyDocument" text type="primary" @click="(event: any) => handleCopyUrl(event, row.requestUrl)" />
<el-button v-if="row.requestUrl" class="ml5" icon="ele-CopyDocument" text type="primary" @click="(event: any) => handleCopyUrl(event, row.requestUrl)" />
{{ row.requestUrl }}
</template>
<template #row_requestBody="{ row, $index }">
@ -121,6 +122,7 @@
</div>
</template>
<!-- 请求日志 -->
<script lang="ts" setup name="sysLogHttp">
import { ElMessage } from 'element-plus';
import { Local } from '/@/utils/storage';
@ -160,7 +162,7 @@ const options = useVxeTable<PageLogHttpOutput>(
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
{ field: 'seq', type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'httpClientName', title: '客户端', minWidth: 110, showOverflow: 'tooltip' },
{ field: 'actionName', title: '模块名', minWidth: 110, showOverflow: 'tooltip' },
{ field: 'httpMethod', title: '请求方式', minWidth: 60, showOverflow: 'tooltip' },
@ -173,10 +175,10 @@ const options = useVxeTable<PageLogHttpOutput>(
{ field: 'responseHeaders', title: '响应头', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'responseBody', title: '响应体', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_responseBody' } },
{ field: 'exception', title: '异常信息', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_exception' } },
{ field: 'startTime', title: '开始时间', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_startTime' } },
{ field: 'endTime', title: '结束时间', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_endTime' } },
{ field: 'elapsed', title: '耗时(毫秒)', minWidth: 90, showOverflow: 'tooltip' },
{ field: 'createUserName', title: '创建用户', minWidth: 90, showOverflow: 'tooltip' },
{ field: 'startTime', title: '开始时间', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_startTime' } },
{ field: 'endTime', title: '结束时间', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_endTime' } },
{ field: 'elapsed', title: '耗时(毫秒)', minWidth: 90, showOverflow: 'tooltip' },
{ field: 'createUserName', title: '创建用户', minWidth: 90, showOverflow: 'tooltip' },
],
},
// vxeGrid()vxe-table
@ -196,7 +198,9 @@ const options = useVxeTable<PageLogHttpOutput>(
//
onMounted(async () => {
state.clientNameList = await getAPI(SysLogHttpApi).apiSysLogHttpHttpClientNameGet().then(res => res.data.result ?? []);
state.clientNameList = await getAPI(SysLogHttpApi)
.apiSysLogHttpHttpClientNameGet()
.then((res) => res.data.result ?? []);
state.localPageParam = Local.get(localPageParamKey) || state.localPageParam;
});
@ -222,9 +226,9 @@ const handleQuery = async (reset = false) => {
//
const handleCopyUrl = (event: PointerEvent, url: string) => {
event.stopPropagation(); //
commonFun.copyText(url);
}
event.stopPropagation(); //
commonFun.copyText(url);
};
//
const resetQuery = async () => {
@ -241,7 +245,7 @@ const resetQuery = async () => {
//
const colors = ['--el-color-primary-light-9', '--el-color-primary-light-7', '--el-color-primary-light-5', '--el-color-primary-light-3', '--el-color-primary-light-1', '--el-color-primary'].map(
(variable) => getComputedStyle(document.documentElement).getPropertyValue(variable).trim()
(variable) => getComputedStyle(document.documentElement).getPropertyValue(variable).trim()
);
const echartsOption = ref({
title: {
@ -345,4 +349,5 @@ const gridEvents: VxeGridListeners<PageLogHttpOutput> = {
},
};
</script>
<style scoped></style>
<style lang="scss" scoped></style>

View File

@ -44,9 +44,9 @@
:check-strictly="!state.strictly"
>
<template #default="{ node }">
<el-icon v-if="node.level == 1" size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-School /></el-icon>
<el-icon v-else-if="node.level == 2" size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Refrigerator /></el-icon>
<el-icon v-else size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-CollectionTag /></el-icon>
<el-icon v-if="node.level == 1" size="16" style="margin-right: 3px; display: inline; vertical-align: middle; color: var(--el-color-primary)"><ele-School /></el-icon>
<el-icon v-else-if="node.level == 2" size="16" style="margin-right: 3px; display: inline; vertical-align: middle; color: var(--el-color-primary)"><ele-Refrigerator /></el-icon>
<el-icon v-else size="16" style="margin-right: 3px; display: inline; vertical-align: middle; color: var(--el-color-primary)"><ele-CollectionTag /></el-icon>
{{ node.label }}
</template>
</el-tree>

View File

@ -145,7 +145,7 @@ const options = useVxeTable<PageRoleOutput>(
{ field: 'orderNo', title: i18n.t('message.list.orderNo'), width: 80, showOverflow: 'tooltip' },
{ field: 'status', title: i18n.t('message.list.status'), width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
{ field: 'record', title: i18n.t('message.list.record'), width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
{ field: 'buttons', title: i18n.t('message.list.operation'), fixed: 'right', width: 540, showOverflow: true, slots: { default: 'row_buttons' } },
{ field: 'buttons', title: i18n.t('message.list.operation'), fixed: 'right', width: 520, showOverflow: true, slots: { default: 'row_buttons' } },
],
},
// vxeGrid()vxe-table

View File

@ -138,6 +138,8 @@ const closeDialog = () => {
//
const preview = () => {
if (state.ruleForm.formater == '') return;
getAPI(SysSerialApi)
.apiSysSerialPreviewPost(state.ruleForm)
.then((res) => {

View File

@ -135,7 +135,9 @@ const options = useVxeTable<PageSerialOutput>(
//
onMounted(async () => {
state.localPageParam = Local.get(localPageParamKey) || state.localPageParam;
state.typeData = await getAPI(SysSerialApi).apiSysSerialTypeListGet().then(res => res.data.result ?? []);
state.typeData = await getAPI(SysSerialApi)
.apiSysSerialTypeListGet()
.then((res) => res.data.result ?? []);
handleQuery(true);
});

View File

@ -69,7 +69,7 @@
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item :label="$t('message.list.jobTitle')" prop="posId" :rules="[{ required: true, message: $t('message.list.jobTitleRequired'), trigger: 'blur' }]">
<el-form-item :label="$t('message.list.jobTitle')">
<el-select v-model="state.ruleForm.posId" :placeholder="$t('message.list.jobTitle')" class="w100">
<el-option v-for="d in state.posData" :key="d.id" :label="d.name" :value="d.id" />
</el-select>
@ -118,11 +118,7 @@
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item
:label="$t('message.list.jobTitle')"
:prop="`extOrgIdList[${k}].posId`"
:rules="[{ required: true, message: $t('message.list.positionRequired'), trigger: 'blur' }]"
>
<el-form-item :label="$t('message.list.jobTitle')">
<el-select v-model="state.ruleForm.extOrgIdList[k].posId" :placeholder="$t('message.list.jobTitle')" class="w100">
<el-option v-for="d in state.posData" :key="d.id" :label="d.name" :value="d.id" />
</el-select>

View File

@ -109,10 +109,10 @@ import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import XEUtils from 'xe-utils';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import { useI18n } from 'vue-i18n';
import { auth } from '/@/utils/authFunction';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import OrgTree from '/@/views/system/org/component/orgTree.vue';
import EditUser from '/@/views/system/user/component/editUser.vue';
@ -153,27 +153,23 @@ const options = useVxeTable<UserOutput>(
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
{ field: 'seq', type: 'seq', title: t('message.list.seq'), width: 60, fixed: 'left' },
// { field: 'avatar', title: t('message.list.avatar'), minWidth: 80, showOverflow: 'tooltip', slots: { default: 'row_avatar' } },
{ field: 'account', title: t('message.list.account'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'nickName', title: t('message.list.nickname'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'realName', title: t('message.list.realName'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'phone', title: t('message.list.phoneNumber'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'birthday', title: t('message.list.birthDate'), minWidth: 100, showOverflow: 'tooltip', formatter: ({ cellValue }: any) => XEUtils.toDateString(cellValue, 'yyyy-MM-dd') },
{ field: 'sex', title: t('message.list.gender'), minWidth: 70, showOverflow: 'tooltip', slots: { default: 'row_sex' } },
{ field: 'accountType', title: t('message.list.accountType'), minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_accountType' } },
{ field: 'account', title: t('message.list.account'), minWidth: 100, showOverflow: 'tooltip' },
{ field: 'nickName', title: t('message.list.nickname'), minWidth: 100, showOverflow: 'tooltip' },
{ field: 'realName', title: t('message.list.realName'), minWidth: 100, showOverflow: 'tooltip' },
{ field: 'phone', title: t('message.list.phoneNumber'), minWidth: 100, showOverflow: 'tooltip' },
// { field: 'birthday', title: t('message.list.birthDate'), minWidth: 100, showOverflow: 'tooltip', formatter: ({ cellValue }: any) => XEUtils.toDateString(cellValue, 'yyyy-MM-dd') },
{ field: 'sex', title: t('message.list.gender'), showOverflow: 'tooltip', slots: { default: 'row_sex' } },
{ field: 'roleName', title: t('message.list.roleSet'), minWidth: 130, showOverflow: 'tooltip' },
{ field: 'orgName', title: t('message.list.organization'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'posName', title: t('message.list.jobTitle'), minWidth: 120, showOverflow: 'tooltip' },
{ field: 'posName', title: t('message.list.jobTitle'), minWidth: 100, showOverflow: 'tooltip' },
{ field: 'jobNum', title: t('message.list.jobNumb'), minWidth: 100, showOverflow: 'tooltip' },
{ field: 'accountType', title: t('message.list.accountType'), minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_accountType' } },
{ field: 'status', title: t('message.list.status'), width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
{ field: 'orderNo', title: t('message.list.orderNo'), width: 80, showOverflow: 'tooltip' },
{ field: 'orderNo', title: t('message.list.orderNo'), showOverflow: 'tooltip' },
{ field: 'record', title: t('message.list.record'), width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
{ field: 'buttons', title: t('message.list.operation'), fixed: 'right', width: 300, showOverflow: true, slots: { default: 'row_buttons' } },
{ field: 'buttons', title: t('message.list.operation'), fixed: 'right', width: 260, showOverflow: true, slots: { default: 'row_buttons' } },
],
},
// vxeGrid()vxe-table