Compare commits

..

10 Commits

47 changed files with 871 additions and 669 deletions

View File

@ -28,9 +28,9 @@
<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.10" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.128" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.128" />
<PackageReference Include="Furion.Pure" Version="4.9.7.128" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.129" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.129" />
<PackageReference Include="Furion.Pure" Version="4.9.7.129" />
<PackageReference Include="Hardware.Info" Version="101.1.0" />
<PackageReference Include="Hashids.net" Version="1.7.0" />
<PackageReference Include="IPTools.China" Version="1.6.0" />
@ -47,7 +47,7 @@
<PackageReference Include="NewLife.Redis" Version="6.3.2025.1001" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="QRCoder" Version="1.7.0" />
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.12.0" />
@ -55,7 +55,7 @@
<PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.266" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.205" />
<PackageReference Include="SSH.NET" Version="2025.0.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.8" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.9" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1328" />
<PackageReference Include="UAParser" Version="3.1.47" />

View File

@ -84,7 +84,7 @@ public class CodeGenColumnConfig : SysCodeGenColumn
/// <summary>
/// 状态字段
/// </summary>
public bool IsStatus => PropertyName == nameof(BaseStatusInput.Status) && DictConfig.Code.Trim('?') == nameof(StatusEnum);
public bool IsStatus => PropertyName == nameof(BaseStatusInput.Status) && DictConfig.Code?.Trim('?') == nameof(StatusEnum);
/// <summary>
/// 是否要联表

View File

@ -122,7 +122,7 @@ public abstract class CodeGenTableStrategyBase<T> : CodeGenStrategy<T> where T :
// input.ColumnList = await CodeGenColumnService.GetColumnList(new BaseIdInput{ Id = codeGen.TableList.First().Id }); // 数据库字段列表,
input.IsOnlyIdPrimary = input.AllFields.Where(u => u.IsPrimarykey).All(u => u.PropertyName == "Id"); // 是否主键只有Id
input.HasStatus = input.AllFields.Any(u => u.PropertyName == nameof(BaseStatusInput.Status) && u.DictConfig.Code.Trim('?') == nameof(StatusEnum)); // 是否有启用禁用字段
input.HasStatus = input.AllFields.Any(u => u.PropertyName == nameof(BaseStatusInput.Status) && u.DictConfig.Code?.Trim('?') == nameof(StatusEnum)); // 是否有启用禁用字段
input.HasJoinTable = input.AllFields.Any(e => e.EffectType is CodeGenEffectTypeEnum.ForeignKey or CodeGenEffectTypeEnum.ApiTreeSelector); // 是否有联表
input.HasUpload = input.UploadFields.Count != 0; // 是否有上传

View File

@ -29,6 +29,13 @@ public partial class SysPos : EntityTenant
[MaxLength(64)]
public string? Code { get; set; }
/// <summary>
/// 类别
/// </summary>
[SugarColumn(ColumnDescription = "类别", Length = 64)]
[MaxLength(64)]
public string? Type { get; set; }
/// <summary>
/// 排序
/// </summary>

View File

@ -4,8 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Furion.Shapeless;
namespace Admin.NET.Core;
/// <summary>
@ -13,13 +11,16 @@ namespace Admin.NET.Core;
/// </summary>
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
{
private readonly IServiceScope _serviceScope;
private readonly IEventPublisher _eventPublisher;
private readonly ILogger<DatabaseLoggingWriter> _logger;
private readonly SysConfigService _sysConfigService;
private readonly IEventPublisher _eventPublisher;
private readonly IServiceScope _serviceScope;
private readonly SqlSugarScopeProvider _db;
public DatabaseLoggingWriter(IServiceScopeFactory serviceScopeFactory, IEventPublisher eventPublisher, ILogger<DatabaseLoggingWriter> logger)
public DatabaseLoggingWriter(
IServiceScopeFactory serviceScopeFactory,
ILogger<DatabaseLoggingWriter> logger,
IEventPublisher eventPublisher)
{
_serviceScope = serviceScopeFactory.CreateScope();
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
@ -94,33 +95,24 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
return;
}
var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
// 获取当前操作者
string account = "", realName = "", userId = "", tenantId = "";
if (loggingMonitor.authorizationClaims != null)
{
var authDict = (loggingMonitor.authorizationClaims as IEnumerable<dynamic>)!.ToDictionary(u => u.type.ToString(), u => u.value.ToString());
account = authDict?.GetValueOrDefault(ClaimConst.Account);
realName = authDict?.GetValueOrDefault(ClaimConst.RealName);
tenantId = authDict?.GetValueOrDefault(ClaimConst.TenantId);
userId = authDict?.GetValueOrDefault(ClaimConst.UserId);
}
var loggingMonitor = JSON.Deserialize<LoggingMonitorDto>(jsonStr);
var userInfo = GetUserInfo(loggingMonitor);
// 优先获取 X-Forwarded-For 头部信息携带的IP地址如nginx代理配置转发
var remoteIPv4 = ((JArray)loggingMonitor.requestHeaders).OfType<JObject>()
.FirstOrDefault(header => (string)header["key"] == "X-Forwarded-For")?["value"]?.ToString();
var reqHeaders = loggingMonitor.RequestHeaders.ToDictionary(u => u.Key, u => u.Value);
var remoteIPv4 = reqHeaders.GetValueOrDefault("X-Forwarded-For")?.ToString();
// 获取IP地理位置
if (string.IsNullOrEmpty(remoteIPv4))
remoteIPv4 = loggingMonitor.remoteIPv4;
if (string.IsNullOrEmpty(remoteIPv4)) remoteIPv4 = loggingMonitor.RemoteIPv4;
(string ipLocation, double? longitude, double? latitude) = CommonHelper.GetIpAddress(remoteIPv4);
// 获取设备信息
var browser = "";
var os = "";
if (loggingMonitor.userAgent != null)
var browser = "";
if (loggingMonitor.UserAgent != null)
{
var client = Parser.GetDefault().Parse(loggingMonitor.userAgent.ToString());
var client = Parser.GetDefault().Parse(loggingMonitor.UserAgent);
browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
}
@ -128,120 +120,100 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
// 捕捉异常,否则会由于 unhandled exception 导致程序崩溃
try
{
// 记录异常日志-发送邮件
if (logMsg.Exception != null || loggingMonitor.exception != null)
var logEntity = new SysLogOp
{
await _db.Insertable(new SysLogEx
{
ControllerName = loggingMonitor.controllerName,
ActionName = loggingMonitor.actionTypeName,
DisplayTitle = loggingMonitor.displayTitle,
Status = loggingMonitor.returnInformation?.httpStatusCode,
RemoteIp = remoteIPv4,
Location = ipLocation,
Longitude = longitude,
Latitude = latitude,
Browser = browser, // loggingMonitor.userAgent,
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
LogDateTime = logMsg.LogDateTime,
Account = account,
RealName = realName,
HttpMethod = loggingMonitor.httpMethod,
RequestUrl = loggingMonitor.requestUrl,
RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
EventId = logMsg.EventId.Id,
ThreadId = logMsg.ThreadId,
TraceId = logMsg.TraceId,
Exception = JSON.Serialize(loggingMonitor.exception),
Message = logMsg.Message,
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
LogLevel = logMsg.LogLevel
}).ExecuteCommandAsync();
ControllerName = loggingMonitor.DisplayName,
ActionName = loggingMonitor.ActionTypeName,
DisplayTitle = loggingMonitor.DisplayTitle,
Status = loggingMonitor.ReturnInformation?.HttpStatusCode?.ToString(),
RemoteIp = remoteIPv4,
Location = ipLocation,
Longitude = longitude,
Latitude = latitude,
Browser = browser,
Os = os,
Elapsed = loggingMonitor.TimeOperationElapsedMilliseconds,
Message = logMsg.Message,
HttpMethod = loggingMonitor.HttpMethod,
RequestUrl = loggingMonitor.RequestUrl,
RequestParam = loggingMonitor.Parameters is { Count: > 0 } ? JSON.Serialize(loggingMonitor.Parameters[0].Value) : null,
ReturnResult = loggingMonitor.ReturnInformation?.Value != null ? JSON.Serialize(loggingMonitor.ReturnInformation?.Value) : null,
Exception = loggingMonitor.Exception == null ? JSON.Serialize(logMsg.Exception) : JSON.Serialize(loggingMonitor.Exception),
LogDateTime = logMsg.LogDateTime,
EventId = logMsg.EventId.Id,
ThreadId = logMsg.ThreadId,
TraceId = logMsg.TraceId,
Account = userInfo.Account,
RealName = userInfo.RealName,
CreateUserId = userInfo.UserId,
CreateUserName = userInfo.RealName,
TenantId = userInfo.TenantId,
LogLevel = logMsg.LogLevel,
};
// 记录异常日志-发送邮件
if (logMsg.Exception != null || loggingMonitor.Exception != null)
{
await _db.Insertable(logEntity.Adapt<SysLogEx>()).ExecuteCommandAsync();
// 将异常日志发送到邮件
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.exception);
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.Exception);
return;
}
// 记录访问日志-登录退出
if (loggingMonitor.actionName == "login" || loggingMonitor.actionName == "loginPhone" || loggingMonitor.actionName == "logout")
if (loggingMonitor.ActionName == "login" || loggingMonitor.ActionName == "loginPhone" || loggingMonitor.ActionName == "logout")
{
if (loggingMonitor.actionName != "logout")
{
dynamic para = Clay.Parse((loggingMonitor.parameters == null) ? null : JSON.Serialize(loggingMonitor.parameters[0].value));
if (loggingMonitor.actionName == "login")
account = para.account;
else if (loggingMonitor.actionName == "loginPhone")
account = para.phone;
}
await _db.Insertable(new SysLogVis
{
ControllerName = loggingMonitor.displayName,
ActionName = loggingMonitor.actionTypeName,
DisplayTitle = loggingMonitor.displayTitle,
Status = loggingMonitor.returnInformation?.httpStatusCode,
RemoteIp = remoteIPv4,
Location = ipLocation,
Longitude = longitude,
Latitude = latitude,
Browser = browser, // loggingMonitor.userAgent,
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
LogDateTime = logMsg.LogDateTime,
Account = account,
RealName = realName,
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
LogLevel = logMsg.LogLevel
}).ExecuteCommandAsync();
await _db.Insertable(logEntity.Adapt<SysLogVis>()).ExecuteCommandAsync();
return;
}
// 记录操作日志
if (!await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysOpLog)) return;
await _db.Insertable(new SysLogOp
{
ControllerName = loggingMonitor.controllerName,
ActionName = loggingMonitor.actionTypeName,
DisplayTitle = loggingMonitor.displayTitle,
Status = loggingMonitor.returnInformation?.httpStatusCode,
RemoteIp = remoteIPv4,
Location = ipLocation,
Longitude = longitude,
Latitude = latitude,
Browser = browser, // loggingMonitor.userAgent,
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
LogDateTime = logMsg.LogDateTime,
Account = account,
RealName = realName,
HttpMethod = loggingMonitor.httpMethod,
RequestUrl = loggingMonitor.requestUrl,
RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
EventId = logMsg.EventId.Id,
ThreadId = logMsg.ThreadId,
TraceId = logMsg.TraceId,
Exception = loggingMonitor.exception == null ? null : JSON.Serialize(loggingMonitor.exception),
Message = logMsg.Message,
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
LogLevel = logMsg.LogLevel
}).ExecuteCommandAsync();
await _db.Insertable(logEntity.Adapt<SysLogOp>()).ExecuteCommandAsync();
await Task.Delay(50); // 延迟 0.05 秒写入数据库,有效减少高频写入数据库导致死锁问题
}
catch (Exception ex)
{
_logger.LogError(ex, "操作日志入库");
// 将异常日志发送到邮件
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, ex);
}
}
/// <summary>
/// 从日志消息中获取用户信息
/// </summary>
/// <param name="loggingMonitor"></param>
/// <returns></returns>
private LoggingUserInfo GetUserInfo(LoggingMonitorDto loggingMonitor)
{
LoggingUserInfo result = new();
if (loggingMonitor.AuthorizationClaims != null)
{
var authDict = loggingMonitor.AuthorizationClaims.ToDictionary(u => u.Type, u => u.Value);
result.UserId = long.TryParse(authDict?.GetValueOrDefault(ClaimConst.UserId) ?? "", out var userId) ? userId : null;
result.Account = authDict?.GetValueOrDefault(ClaimConst.Account);
result.RealName = authDict?.GetValueOrDefault(ClaimConst.RealName);
result.TenantId = long.TryParse(authDict?.GetValueOrDefault(ClaimConst.TenantId) ?? "", out var tenantId) ? tenantId : null;
}
// 登陆时没有用户Id需要根据入参获取
if (result.UserId == null && loggingMonitor.ActionName == "login" && loggingMonitor.Parameters is { Count: > 0 })
{
result.Account = (loggingMonitor.Parameters[0].Value as JObject)!.GetValue("account")?.ToString();
if (!string.IsNullOrEmpty(result.Account))
{
var db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
var user = db.Queryable<SysUser>().First(u => u.Account == result.Account);
result.TenantId = user?.TenantId;
result.RealName = user?.RealName;
result.UserId = user?.Id;
}
}
return result;
}
/// <summary>
/// 释放服务作用域
/// </summary>

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//

View File

@ -151,6 +151,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
new SysMenu{ Id=1310000000394, Pid=1310000000391, Title="下载", Permission="sysFile/downloadFile", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000395, Pid=1310000000391, Title="删除", Permission="sysFile/delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000396, Pid=1310000000391, Title="编辑", Permission="sysFile/update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2023-10-27 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000397, Pid=1310000000391, Title="预览", Permission="sysFile/preview", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2023-10-27 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000401, Pid=1310000000301, Title="打印模板", Path="/platform/print", Name="sysPrint", Component="/system/print/index", Icon="ele-Printer", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=190 },
new SysMenu{ Id=1310000000402, Pid=1310000000401, Title="查询", Permission="sysPrint/page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },

View File

@ -63,6 +63,8 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
new SysRoleMenu{ Id=1300000000164, RoleId=roleList[0].Id, MenuId=1310000000154 },
new SysRoleMenu{ Id=1300000000165, RoleId=roleList[0].Id, MenuId=1310000000155 },
new SysRoleMenu{ Id=1300000000166, RoleId=roleList[0].Id, MenuId=1310000000156 },
new SysRoleMenu{ Id=1300000000167, RoleId=roleList[0].Id, MenuId=1310000000157 },
new SysRoleMenu{ Id=1300000000168, RoleId=roleList[0].Id, MenuId=1310000000158 },
// 个人中心
new SysRoleMenu{ Id=1300000000171, RoleId=roleList[0].Id, MenuId=1310000000161 },
new SysRoleMenu{ Id=1300000000172, RoleId=roleList[0].Id, MenuId=1310000000162 },
@ -138,6 +140,7 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
new SysRoleMenu{ Id=1300000000294, RoleId=roleList[0].Id, MenuId=1310000000394 },
new SysRoleMenu{ Id=1300000000295, RoleId=roleList[0].Id, MenuId=1310000000395 },
new SysRoleMenu{ Id=1300000000296, RoleId=roleList[0].Id, MenuId=1310000000396 },
new SysRoleMenu{ Id=1300000000297, RoleId=roleList[0].Id, MenuId=1310000000397 },
// 打印模板
new SysRoleMenu{ Id=1300000001401, RoleId=roleList[0].Id, MenuId=1310000000401 },
new SysRoleMenu{ Id=1300000001402, RoleId=roleList[0].Id, MenuId=1310000000402 },
@ -167,6 +170,13 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
new SysRoleMenu{ Id=1300000001446, RoleId=roleList[0].Id, MenuId=1310000000446 },
// 更新日志
new SysRoleMenu{ Id=1300000001451, RoleId=roleList[0].Id, MenuId=1310000000451 },
// 流水序号
new SysRoleMenu{ Id=1300000001501, RoleId=roleList[0].Id, MenuId=1310000000471 },
new SysRoleMenu{ Id=1300000001502, RoleId=roleList[0].Id, MenuId=1310000000472 },
new SysRoleMenu{ Id=1300000001503, RoleId=roleList[0].Id, MenuId=1310000000473 },
new SysRoleMenu{ Id=1300000001504, RoleId=roleList[0].Id, MenuId=1310000000474 },
new SysRoleMenu{ Id=1300000001505, RoleId=roleList[0].Id, MenuId=1310000000475 },
new SysRoleMenu{ Id=1300000001506, RoleId=roleList[0].Id, MenuId=1310000000476 },
////// 日志管理
new SysRoleMenu{ Id=1300000000301, RoleId=roleList[0].Id, MenuId=1310000000501 },
new SysRoleMenu{ Id=1300000000311, RoleId=roleList[0].Id, MenuId=1310000000511 },
@ -187,6 +197,23 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
new SysRoleMenu{ Id=1300000000351, RoleId=roleList[0].Id, MenuId=1310000000551 },
new SysRoleMenu{ Id=1300000000352, RoleId=roleList[0].Id, MenuId=1310000000552 },
new SysRoleMenu{ Id=1300000000353, RoleId=roleList[0].Id, MenuId=1310000000553 },
new SysRoleMenu{ Id=1300000000361, RoleId=roleList[0].Id, MenuId=1310000000561 },
new SysRoleMenu{ Id=1300000000362, RoleId=roleList[0].Id, MenuId=1310000000562 },
new SysRoleMenu{ Id=1300000000363, RoleId=roleList[0].Id, MenuId=1310000000563 },
////// 报表开发
new SysRoleMenu{ Id=1300000001601, RoleId=roleList[0].Id, MenuId=1310000000701 },
new SysRoleMenu{ Id=1300000001611, RoleId=roleList[0].Id, MenuId=1310000000711 },
new SysRoleMenu{ Id=1300000001612, RoleId=roleList[0].Id, MenuId=1310000000712 },
new SysRoleMenu{ Id=1300000001613, RoleId=roleList[0].Id, MenuId=1310000000713 },
new SysRoleMenu{ Id=1300000001614, RoleId=roleList[0].Id, MenuId=1310000000714 },
new SysRoleMenu{ Id=1300000001615, RoleId=roleList[0].Id, MenuId=1310000000715 },
new SysRoleMenu{ Id=1300000001616, RoleId=roleList[0].Id, MenuId=1310000000716 },
new SysRoleMenu{ Id=1300000001621, RoleId=roleList[0].Id, MenuId=1310000000721 },
new SysRoleMenu{ Id=1300000001622, RoleId=roleList[0].Id, MenuId=1310000000722 },
new SysRoleMenu{ Id=1300000001623, RoleId=roleList[0].Id, MenuId=1310000000723 },
new SysRoleMenu{ Id=1300000001624, RoleId=roleList[0].Id, MenuId=1310000000724 },
new SysRoleMenu{ Id=1300000001625, RoleId=roleList[0].Id, MenuId=1310000000725 },
new SysRoleMenu{ Id=1300000001631, RoleId=roleList[0].Id, MenuId=1310000000731 },
////// 帮助文档
new SysRoleMenu{ Id=1300000000401, RoleId=roleList[0].Id, MenuId=1320000000101 },
new SysRoleMenu{ Id=1300000000402, RoleId=roleList[0].Id, MenuId=1320000000111 },

View File

@ -31,53 +31,35 @@ public class PageFileInput : BasePageInput
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
}
/// <summary>
/// 多文件上传
/// </summary>
public class UploadFilesInput : BaseUploadFileInput
{
/// <summary>
/// 文件集合
/// </summary>
[Required]
public IFormFileCollection Files { get; set; }
}
/// <summary>
/// 上传文件
/// </summary>
public class UploadFileInput
public class UploadFileInput : BaseUploadFileInput
{
/// <summary>
/// 文件
/// </summary>
[Required]
public IFormFile File { get; set; }
/// <summary>
/// 文件类别
/// </summary>
/// <example></example>
public string FileType { get; set; }
/// <summary>
/// 文件别名
/// </summary>
/// <example></example>
public string FileAlias { get; set; }
/// <summary>
/// 是否公开
/// </summary>
public bool IsPublic { get; set; } = false;
/// <summary>
/// 允许格式:.jpeg.jpg.png.bmp.gif.tif
/// </summary>
/// <example></example>
public string AllowSuffix { get; set; }
/// <summary>
/// 业务数据Id
/// </summary>
public long DataId { get; set; }
/// <summary>
/// 上传用户Id解决跨租户上传时用户所属不一致问题
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public long UserId { get; set; }
}
/// <summary>
@ -123,6 +105,44 @@ public class UploadFileFromBase64Input
/// </summary>
public long? DataId { get; set; }
/// <summary>
/// 上传用户Id解决跨租户上传时用户所属不一致问题
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public long UserId { get; set; }
}
public class BaseUploadFileInput
{
/// <summary>
/// 文件类别
/// </summary>
/// <example></example>
public string FileType { get; set; }
/// <summary>
/// 文件别名
/// </summary>
/// <example></example>
public string FileAlias { get; set; }
/// <summary>
/// 是否公开
/// </summary>
public bool IsPublic { get; set; } = false;
/// <summary>
/// 允许格式:.jpeg.jpg.png.bmp.gif.tif
/// </summary>
/// <example></example>
public string AllowSuffix { get; set; }
/// <summary>
/// 业务数据Id
/// </summary>
public long DataId { get; set; }
/// <summary>
/// 上传用户Id解决跨租户上传时用户所属不一致问题
/// </summary>

View File

@ -60,15 +60,11 @@ public class SysFileService : IDynamicApiController, ITransient
[DisplayName("获取文件分页列表")]
public async Task<SqlSugarPagedList<SysFile>> Page(PageFileInput input)
{
// 获取所有公开文件
var publicList = _sysFileRep.AsQueryable().ClearFilter<ITenantIdFilter>().Where(u => u.IsPublic == true);
// 获取私有文件
var privateList = _sysFileRep.AsQueryable().Where(u => u.IsPublic == false);
// 合并公开和私有并分页
return await _sysFileRep.Context.UnionAll(publicList, privateList)
return await _sysFileRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
.WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
.WhereIF(!string.IsNullOrWhiteSpace(input.FilePath), u => u.FilePath.Contains(input.FilePath.Trim()))
.OrderBy(u => u.CreateTime, OrderByType.Desc)
.ToPagedListAsync(input.Page, input.PageSize);
}
@ -109,13 +105,32 @@ public class SysFileService : IDynamicApiController, ITransient
/// <param name="files"></param>
/// <returns></returns>
[DisplayName("上传多文件")]
public List<SysFile> UploadFiles([Required] List<IFormFile> files)
public List<SysFile> UploadFileList([Required] List<IFormFile> files)
{
var fileList = new List<SysFile>();
files.ForEach(file => fileList.Add(UploadFile(new UploadFileInput { File = file }).Result));
return fileList;
}
/// <summary>
/// 上传多文件 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("上传多文件")]
public async Task<List<SysFile>> UploadFiles([FromForm] UploadFilesInput input)
{
var fileList = new List<SysFile>();
foreach (var file in input.Files)
{
var uploadFileInput = input.Adapt<UploadFileInput>();
uploadFileInput.File = file;
var sysFile = await UploadFile(uploadFileInput);
fileList.Add(sysFile);
}
return fileList;
}
/// <summary>
/// 根据文件Id或Url下载 🔖
/// </summary>

View File

@ -104,7 +104,18 @@ public class SysOrgService : IDynamicApiController, ITransient
public async Task<List<SysOrg>> GetChildTree(long pid, int level)
{
var iSugarQueryable = _sysOrgRep.AsQueryable().OrderBy(u => new { u.OrderNo });
return await iSugarQueryable.Where(u => u.Level < level).ToTreeAsync(u => u.Children, u => u.Pid, pid);
return await iSugarQueryable.Where(u => u.Level < level).ToChildListAsync(u => u.Pid, pid, true);
}
/// <summary>
/// 获取当前用户机构子树 🔖
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
[DisplayName("获取当前用户机构子树")]
public async Task<List<SysOrg>> GetUserChildTree(int level = 100)
{
return await GetChildTree(_userManager.OrgId, level);
}
/// <summary>
@ -119,7 +130,7 @@ public class SysOrgService : IDynamicApiController, ITransient
if (!_userManager.SuperAdmin && input.Pid == 0)
throw Oops.Oh(ErrorCodeEnum.D2009);
if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name || u.Code == input.Code))
throw Oops.Oh(ErrorCodeEnum.D2002);
if (!_userManager.SuperAdmin && input.Pid != 0)
@ -189,7 +200,7 @@ public class SysOrgService : IDynamicApiController, ITransient
if (input.Id == input.Pid)
throw Oops.Oh(ErrorCodeEnum.D2001);
if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id))
if (await _sysOrgRep.IsAnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id))
throw Oops.Oh(ErrorCodeEnum.D2002);
// 父Id不能为自己的子节点

View File

@ -17,6 +17,7 @@ public class PosDto
/// 名称
/// </summary>
[ImporterHeader(Name = "名称")]
[Required(ErrorMessage = "名称不能为空")]
[ExporterHeader(DisplayName = "名称", IsBold = true)]
public string Name { get; set; }
@ -27,6 +28,13 @@ public class PosDto
[ExporterHeader(DisplayName = "编码", IsBold = true)]
public string Code { get; set; }
/// <summary>
/// 类别
/// </summary>
[ImporterHeader(Name = "类别")]
[ExporterHeader(DisplayName = "类别", IsBold = true)]
public string Type { get; set; }
/// <summary>
/// 排序
/// </summary>
@ -45,7 +53,6 @@ public class PosDto
/// 状态
/// </summary>
[ImporterHeader(Name = "状态")]
[Required(ErrorMessage = "状态不能为空")]
[ValueMapping("启用", 1)]
[ValueMapping("停用", 2)]
[ExporterHeader(DisplayName = "状态", IsBold = true)]

View File

@ -146,9 +146,15 @@ public class SysPosService : IDynamicApiController, ITransient
if (res == null || res.Exception != null)
throw Oops.Oh(res.Exception);
var importData = res.Data.ToList();
var posList = new List<SysPos>();
var importData = res.Data.ToList().GroupBy(u => new { u.Name, u.Type }).Select(u => u.First()).ToList(); // 以名称和类型除重
foreach (var item in importData)
{
if (string.IsNullOrWhiteSpace(item.Name)) continue;
posList.Add(item.Adapt<SysPos>());
}
// 按照编码条件进行批量更新或者新增
await _sysPosRep.Context.Storageable(importData.Adapt<List<SysPos>>()).WhereColumns(u => u.Code).ExecuteCommandAsync();
await _sysPosRep.Context.Storageable(posList).WhereColumns(u => u.Code).ExecuteCommandAsync();
}
/// <summary>

View File

@ -467,6 +467,32 @@ public class SysUserService : IDynamicApiController, ITransient
return await _sysUserExtOrgService.GetUserExtOrgList(userId);
}
/// <summary>
/// 获取用户能看到的其他用户集合 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取用户能看到的其他用户集合")]
public async Task<List<UserOutput>> GetOwnUserList()
{
// 获取用户拥有的机构集合
var orgList = await _sysOrgService.GetUserOrgIdList();
return await _sysUserRep.AsQueryable()
.LeftJoin<SysOrg>((u, a) => u.OrgId == a.Id)
.LeftJoin<SysPos>((u, a, b) => u.PosId == b.Id)
.Where(u => u.AccountType != AccountTypeEnum.SuperAdmin)
.Where(u => orgList.Contains(u.OrgId))
.OrderBy(u => new { u.OrderNo, u.Id })
.Select((u, a, b) => new UserOutput
{
OrgName = a.Name,
PosName = b.Name,
RoleName = SqlFunc.Subqueryable<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","),
DomainAccount = SqlFunc.Subqueryable<SysUserLdap>().Where(m => m.UserId == u.Id).Select(m => m.Account)
}, true)
.ToListAsync();
}
/// <summary>
/// 强制下线账号和失效Token
/// </summary>

View File

@ -14,8 +14,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="Furion.Xunit" Version="4.9.7.128" />
<PackageReference Include="Furion.Pure" Version="4.9.7.128">
<PackageReference Include="Furion.Xunit" Version="4.9.7.129" />
<PackageReference Include="Furion.Pure" Version="4.9.7.129">
<ExcludeAssets>compile</ExcludeAssets>
</PackageReference>
<PackageReference Include="xunit.assert" Version="2.9.3" />

View File

@ -471,17 +471,20 @@ public class Startup : AppStartup
});
// 配置Swagger-Knife4UI路由前缀一致代表独立不同则代表共存
app.UseKnife4UI(options =>
if (App.GetConfig<bool>("AppSettings:InjectSpecificationDocument", true))
{
options.RoutePrefix = "kapi";
options.ConfigObject.DisplayOperationId = true;
options.ConfigObject.DisplayRequestDuration = true;
foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
app.UseKnife4UI(options =>
{
// 兼容二级虚拟目录转发(配置二级域名转发,需要 Swagger.json 的 ServerDir 配置项)
options.SwaggerEndpoint(string.Concat("..", groupInfo.RouteTemplate.AsSpan(groupInfo.RouteTemplate.IndexOf("/swagger/"))), groupInfo.Title);
}
});
options.RoutePrefix = "kapi";
options.ConfigObject.DisplayOperationId = true;
options.ConfigObject.DisplayRequestDuration = true;
foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
{
// 兼容二级虚拟目录转发(配置二级域名转发,需要 Swagger.json 的 ServerDir 配置项)
options.SwaggerEndpoint(string.Concat("..", groupInfo.RouteTemplate.AsSpan(groupInfo.RouteTemplate.IndexOf("/swagger/"))), groupInfo.Title);
}
});
}
app.UseInject(string.Empty, options =>
{

View File

@ -17,15 +17,15 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="microsoft.semantickernel" Version="1.65.0" />
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.65.0" />
<PackageReference Include="microsoft.semantickernel" Version="1.66.0" />
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="1.66.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.65.0" />
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.65.0" />
<PackageReference Include="Microsoft.SemanticKernel.PromptTemplates.Handlebars" Version="1.66.0" />
<PackageReference Include="Microsoft.SemanticKernel.Yaml" Version="1.66.0" />
</ItemGroup>
<ItemGroup>

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2025.10.08",
"lastBuildTime": "2025.10.12",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -49,7 +49,7 @@
"jsplumb": "^2.15.6",
"lodash-es": "^4.17.21",
"magic-string": "^0.30.19",
"md-editor-v3": "^6.0.1",
"md-editor-v3": "^6.1.0",
"mitt": "^3.0.1",
"monaco-editor": "^0.54.0",
"mqtt": "^5.14.0",
@ -62,7 +62,7 @@
"qs": "^6.14.0",
"relation-graph": "^2.2.11",
"screenfull": "^6.0.2",
"sm-crypto-v2": "^1.14.0",
"sm-crypto-v2": "^1.15.0",
"sortablejs": "^1.15.6",
"splitpanes": "^4.0.4",
"sql-formatter": "^15.6.10",
@ -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.9.41",
"vxe-table": "^4.16.20",
"vxe-pc-ui": "^4.9.42",
"vxe-table": "^4.16.21",
"xe-utils": "^3.7.9",
"xlsx-js-style": "^1.2.0"
},
@ -90,7 +90,7 @@
"@iconify/vue": "^5.0.0",
"@plugin-web-update-notification/vite": "^2.0.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.18.8",
"@types/node": "^22.18.9",
"@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.46.0",

View File

@ -12,9 +12,6 @@
* Do not edit the class manually.
*/
export * from './apis/apijsonapi';
export * from './apis/llmchange-model-test-api';
export * from './apis/llmtest-api';
export * from './apis/sse-service-api';
export * from './apis/sys-alipay-api';
export * from './apis/sys-auth-api';
export * from './apis/sys-cache-api';

View File

@ -1,139 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Configuration } from '../configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
import { AdminNETResultString } from '../models';
import { LLMModelInput } from '../models';
/**
* LLMChangeModelTestApi - axios parameter creator
* @export
*/
export const LLMChangeModelTestApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary 使 OpenAIAzure OpenAIGoogle Gemini等
* @param {LLMModelInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiLLMChangeModelTestTestSwitchPost: async (body?: LLMModelInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/lLMChangeModelTest/testSwitch`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
}
};
/**
* LLMChangeModelTestApi - functional programming interface
* @export
*/
export const LLMChangeModelTestApiFp = function(configuration?: Configuration) {
return {
/**
*
* @summary 使 OpenAIAzure OpenAIGoogle Gemini等
* @param {LLMModelInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiLLMChangeModelTestTestSwitchPost(body?: LLMModelInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultString>>> {
const localVarAxiosArgs = await LLMChangeModelTestApiAxiosParamCreator(configuration).apiLLMChangeModelTestTestSwitchPost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
}
};
/**
* LLMChangeModelTestApi - factory interface
* @export
*/
export const LLMChangeModelTestApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
return {
/**
*
* @summary 使 OpenAIAzure OpenAIGoogle Gemini等
* @param {LLMModelInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiLLMChangeModelTestTestSwitchPost(body?: LLMModelInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultString>> {
return LLMChangeModelTestApiFp(configuration).apiLLMChangeModelTestTestSwitchPost(body, options).then((request) => request(axios, basePath));
},
};
};
/**
* LLMChangeModelTestApi - object-oriented interface
* @export
* @class LLMChangeModelTestApi
* @extends {BaseAPI}
*/
export class LLMChangeModelTestApi extends BaseAPI {
/**
*
* @summary 使 OpenAIAzure OpenAIGoogle Gemini等
* @param {LLMModelInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof LLMChangeModelTestApi
*/
public async apiLLMChangeModelTestTestSwitchPost(body?: LLMModelInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultString>> {
return LLMChangeModelTestApiFp(this.configuration).apiLLMChangeModelTestTestSwitchPost(body, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -1,130 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Configuration } from '../configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
import { AdminNETResultString } from '../models';
/**
* LLMTestApi - axios parameter creator
* @export
*/
export const LLMTestApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary 使使使
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiLLMTestTestPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/lLMTest/test`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
}
};
/**
* LLMTestApi - functional programming interface
* @export
*/
export const LLMTestApiFp = function(configuration?: Configuration) {
return {
/**
*
* @summary 使使使
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiLLMTestTestPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultString>>> {
const localVarAxiosArgs = await LLMTestApiAxiosParamCreator(configuration).apiLLMTestTestPost(options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
}
};
/**
* LLMTestApi - factory interface
* @export
*/
export const LLMTestApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
return {
/**
*
* @summary 使使使
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiLLMTestTestPost(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultString>> {
return LLMTestApiFp(configuration).apiLLMTestTestPost(options).then((request) => request(axios, basePath));
},
};
};
/**
* LLMTestApi - object-oriented interface
* @export
* @class LLMTestApi
* @extends {BaseAPI}
*/
export class LLMTestApi extends BaseAPI {
/**
*
* @summary 使使使
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof LLMTestApi
*/
public async apiLLMTestTestPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultString>> {
return LLMTestApiFp(this.configuration).apiLLMTestTestPost(options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -1,134 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Configuration } from '../configuration';
// Some imports not used depending on template conditions
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
/**
* SseServiceApi - axios parameter creator
* @export
*/
export const SseServiceApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @param {number} id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
sseChatIdGet: async (id: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'id' is not null or undefined
if (id === null || id === undefined) {
throw new RequiredError('id','Required parameter id was null or undefined when calling sseChatIdGet.');
}
const localVarPath = `/sse/chat/{id}`
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
}
};
/**
* SseServiceApi - functional programming interface
* @export
*/
export const SseServiceApiFp = function(configuration?: Configuration) {
return {
/**
*
* @param {number} id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async sseChatIdGet(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await SseServiceApiAxiosParamCreator(configuration).sseChatIdGet(id, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
}
};
/**
* SseServiceApi - factory interface
* @export
*/
export const SseServiceApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
return {
/**
*
* @param {number} id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async sseChatIdGet(id: number, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SseServiceApiFp(configuration).sseChatIdGet(id, options).then((request) => request(axios, basePath));
},
};
};
/**
* SseServiceApi - object-oriented interface
* @export
* @class SseServiceApi
* @extends {BaseAPI}
*/
export class SseServiceApi extends BaseAPI {
/**
*
* @param {number} id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SseServiceApi
*/
public async sseChatIdGet(id: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SseServiceApiFp(this.configuration).sseChatIdGet(id, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -630,6 +630,59 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysFileUploadFileListPostForm: async (files?: Array<Blob>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysFile/uploadFileList`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
const localVarFormParams = new FormData();
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
if (files) {
files.forEach((element) => {
localVarFormParams.append('files', element as any);
})
}
localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = localVarFormParams;
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -716,10 +769,16 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {string} [fileType]
* @param {string} [fileAlias]
* @param {boolean} [isPublic]
* @param {string} [allowSuffix]
* @param {number} [dataId]
* @param {number} [userId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysFileUploadFilesPostForm: async (files?: Array<Blob>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
apiSysFileUploadFilesPostForm: async (files?: Array<Blob>, fileType?: string, fileAlias?: string, isPublic?: boolean, allowSuffix?: string, dataId?: number, userId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysFile/uploadFiles`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@ -743,10 +802,34 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
if (files) {
files.forEach((element) => {
localVarFormParams.append('files', element as any);
localVarFormParams.append('Files', element as any);
})
}
if (fileType !== undefined) {
localVarFormParams.append('FileType', fileType as any);
}
if (fileAlias !== undefined) {
localVarFormParams.append('FileAlias', fileAlias as any);
}
if (isPublic !== undefined) {
localVarFormParams.append('IsPublic', isPublic as any);
}
if (allowSuffix !== undefined) {
localVarFormParams.append('AllowSuffix', allowSuffix as any);
}
if (dataId !== undefined) {
localVarFormParams.append('DataId', dataId as any);
}
if (userId !== undefined) {
localVarFormParams.append('UserId', userId as any);
}
localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
@ -1107,6 +1190,20 @@ export const SysFileApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysFileUploadFileListPostForm(files?: Array<Blob>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSysFile>>> {
const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileUploadFileListPostForm(files, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -1131,11 +1228,17 @@ export const SysFileApiFp = function(configuration?: Configuration) {
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {string} [fileType]
* @param {string} [fileAlias]
* @param {boolean} [isPublic]
* @param {string} [allowSuffix]
* @param {number} [dataId]
* @param {number} [userId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysFileUploadFilesPostForm(files?: Array<Blob>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSysFile>>> {
const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileUploadFilesPostForm(files, options);
async apiSysFileUploadFilesPostForm(files?: Array<Blob>, fileType?: string, fileAlias?: string, isPublic?: boolean, allowSuffix?: string, dataId?: number, userId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSysFile>>> {
const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileUploadFilesPostForm(files, fileType, fileAlias, isPublic, allowSuffix, dataId, userId, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
@ -1316,6 +1419,16 @@ export const SysFileApiFactory = function (configuration?: Configuration, basePa
async apiSysFileUploadFileFromBase64Post(body?: UploadFileFromBase64Input, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultSysFile>> {
return SysFileApiFp(configuration).apiSysFileUploadFileFromBase64Post(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysFileUploadFileListPostForm(files?: Array<Blob>, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(configuration).apiSysFileUploadFileListPostForm(files, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -1336,11 +1449,17 @@ export const SysFileApiFactory = function (configuration?: Configuration, basePa
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {string} [fileType]
* @param {string} [fileAlias]
* @param {boolean} [isPublic]
* @param {string} [allowSuffix]
* @param {number} [dataId]
* @param {number} [userId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysFileUploadFilesPostForm(files?: Array<Blob>, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(configuration).apiSysFileUploadFilesPostForm(files, options).then((request) => request(axios, basePath));
async apiSysFileUploadFilesPostForm(files?: Array<Blob>, fileType?: string, fileAlias?: string, isPublic?: boolean, allowSuffix?: string, dataId?: number, userId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(configuration).apiSysFileUploadFilesPostForm(files, fileType, fileAlias, isPublic, allowSuffix, dataId, userId, options).then((request) => request(axios, basePath));
},
/**
*
@ -1518,6 +1637,17 @@ export class SysFileApi extends BaseAPI {
public async apiSysFileUploadFileFromBase64Post(body?: UploadFileFromBase64Input, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultSysFile>> {
return SysFileApiFp(this.configuration).apiSysFileUploadFileFromBase64Post(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysFileApi
*/
public async apiSysFileUploadFileListPostForm(files?: Array<Blob>, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(this.configuration).apiSysFileUploadFileListPostForm(files, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
@ -1539,12 +1669,18 @@ export class SysFileApi extends BaseAPI {
*
* @summary 🔖
* @param {Array<Blob>} [files]
* @param {string} [fileType]
* @param {string} [fileAlias]
* @param {boolean} [isPublic]
* @param {string} [allowSuffix]
* @param {number} [dataId]
* @param {number} [userId]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysFileApi
*/
public async apiSysFileUploadFilesPostForm(files?: Array<Blob>, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(this.configuration).apiSysFileUploadFilesPostForm(files, options).then((request) => request(this.axios, this.basePath));
public async apiSysFileUploadFilesPostForm(files?: Array<Blob>, fileType?: string, fileAlias?: string, isPublic?: boolean, allowSuffix?: string, dataId?: number, userId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSysFile>> {
return SysFileApiFp(this.configuration).apiSysFileUploadFilesPostForm(files, fileType, fileAlias, isPublic, allowSuffix, dataId, userId, options).then((request) => request(this.axios, this.basePath));
}
/**
*

View File

@ -289,6 +289,55 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysOrgUserChildTreeLevelGet: async (level: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'level' is not null or undefined
if (level === null || level === undefined) {
throw new RequiredError('level','Required parameter level was null or undefined when calling apiSysOrgUserChildTreeLevelGet.');
}
const localVarPath = `/api/sysOrg/userChildTree/{level}`
.replace(`{${"level"}}`, encodeURIComponent(String(level)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
@ -377,6 +426,20 @@ export const SysOrgApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysOrgUserChildTreeLevelGet(level: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSysOrg>>> {
const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).apiSysOrgUserChildTreeLevelGet(level, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
}
};
@ -440,6 +503,16 @@ export const SysOrgApiFactory = function (configuration?: Configuration, basePat
async apiSysOrgUpdatePost(body?: UpdateOrgInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysOrgApiFp(configuration).apiSysOrgUpdatePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysOrgUserChildTreeLevelGet(level: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSysOrg>> {
return SysOrgApiFp(configuration).apiSysOrgUserChildTreeLevelGet(level, options).then((request) => request(axios, basePath));
},
};
};
@ -509,4 +582,15 @@ export class SysOrgApi extends BaseAPI {
public async apiSysOrgUpdatePost(body?: UpdateOrgInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysOrgApiFp(this.configuration).apiSysOrgUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysOrgApi
*/
public async apiSysOrgUserChildTreeLevelGet(level: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSysOrg>> {
return SysOrgApiFp(this.configuration).apiSysOrgUserChildTreeLevelGet(level, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@ -23,6 +23,7 @@ import { AdminNETResultGrantRoleOutput } from '../models';
import { AdminNETResultInt32 } from '../models';
import { AdminNETResultInt64 } from '../models';
import { AdminNETResultListSysUserExtOrg } from '../models';
import { AdminNETResultListUserOutput } from '../models';
import { AdminNETResultSqlSugarPagedListUserOutput } from '../models';
import { AdminNETResultString } from '../models';
import { AdminNETResultSysUser } from '../models';
@ -374,6 +375,49 @@ export const SysUserApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysUserOwnUserListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysUser/ownUserList`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -811,6 +855,19 @@ export const SysUserApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysUserOwnUserListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListUserOutput>>> {
const localVarAxiosArgs = await SysUserApiAxiosParamCreator(configuration).apiSysUserOwnUserListGet(options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -986,6 +1043,15 @@ export const SysUserApiFactory = function (configuration?: Configuration, basePa
async apiSysUserOwnRoleListUserIdGet(userId: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultGrantRoleOutput>> {
return SysUserApiFp(configuration).apiSysUserOwnRoleListUserIdGet(userId, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysUserOwnUserListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListUserOutput>> {
return SysUserApiFp(configuration).apiSysUserOwnUserListGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -1141,6 +1207,16 @@ export class SysUserApi extends BaseAPI {
public async apiSysUserOwnRoleListUserIdGet(userId: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultGrantRoleOutput>> {
return SysUserApiFp(this.configuration).apiSysUserOwnRoleListUserIdGet(userId, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysUserApi
*/
public async apiSysUserOwnUserListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListUserOutput>> {
return SysUserApiFp(this.configuration).apiSysUserOwnUserListGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖

View File

@ -102,6 +102,14 @@ export interface AddPosInput {
*/
code?: string | null;
/**
*
*
* @type {string}
* @memberof AddPosInput
*/
type?: string | null;
/**
*
*

View File

@ -0,0 +1,71 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { UserOutput } from './user-output';
/**
*
*
* @export
* @interface AdminNETResultListUserOutput
*/
export interface AdminNETResultListUserOutput {
/**
*
*
* @type {number}
* @memberof AdminNETResultListUserOutput
*/
code?: number;
/**
* successwarningerror
*
* @type {string}
* @memberof AdminNETResultListUserOutput
*/
type?: string | null;
/**
*
*
* @type {string}
* @memberof AdminNETResultListUserOutput
*/
message?: string | null;
/**
*
*
* @type {Array<UserOutput>}
* @memberof AdminNETResultListUserOutput
*/
result?: Array<UserOutput> | null;
/**
*
*
* @type {any}
* @memberof AdminNETResultListUserOutput
*/
extras?: any | null;
/**
*
*
* @type {Date}
* @memberof AdminNETResultListUserOutput
*/
time?: Date;
}

View File

@ -94,6 +94,7 @@ export * from './admin-netresult-list-sys-user-ldap';
export * from './admin-netresult-list-sys-wechat-refund';
export * from './admin-netresult-list-table-output';
export * from './admin-netresult-list-tree-node';
export * from './admin-netresult-list-user-output';
export * from './admin-netresult-login-output';
export * from './admin-netresult-login-user-output';
export * from './admin-netresult-notice-output';
@ -309,7 +310,6 @@ export * from './job-trigger-input';
export * from './join-config';
export * from './join-config-table-column';
export * from './key-value-pair-string-string';
export * from './llmmodel-input';
export * from './layout-kind';
export * from './list-schedule-input';
export * from './log-input';
@ -485,6 +485,7 @@ export * from './sys-dict-type';
export * from './sys-file';
export * from './sys-file-upload-avatar-body';
export * from './sys-file-upload-file-body';
export * from './sys-file-upload-file-list-body';
export * from './sys-file-upload-files-body';
export * from './sys-file-upload-signature-body';
export * from './sys-info-input';

View File

@ -113,4 +113,12 @@ export interface PageFileInput {
* @memberof PageFileInput
*/
endTime?: Date | null;
/**
*
*
* @type {string}
* @memberof PageFileInput
*/
filePath?: string | null;
}

View File

@ -110,6 +110,14 @@ export interface PagePosOutput {
*/
code?: string | null;
/**
*
*
* @type {string}
* @memberof PagePosOutput
*/
type?: string | null;
/**
*
*

View File

@ -110,6 +110,14 @@ export interface PosOutput {
*/
code?: string | null;
/**
*
*
* @type {string}
* @memberof PosOutput
*/
type?: string | null;
/**
*
*

View File

@ -13,26 +13,16 @@
*/
/**
* LLM模型输入
*
*
* @export
* @interface LLMModelInput
* @interface SysFileUploadFileListBody
*/
export interface LLMModelInput {
export interface SysFileUploadFileListBody {
/**
*
*
* @type {string}
* @memberof LLMModelInput
* @type {Array<Blob>}
* @memberof SysFileUploadFileListBody
*/
productName?: string | null;
/**
* ID
*
* @type {string}
* @memberof LLMModelInput
*/
modelId?: string | null;
files: Array<Blob>;
}

View File

@ -21,8 +21,58 @@
export interface SysFileUploadFilesBody {
/**
*
*
* @type {Array<Blob>}
* @memberof SysFileUploadFilesBody
*/
files: Array<Blob>;
/**
*
*
* @type {string}
* @memberof SysFileUploadFilesBody
*/
fileType?: string;
/**
*
*
* @type {string}
* @memberof SysFileUploadFilesBody
*/
fileAlias?: string;
/**
*
*
* @type {boolean}
* @memberof SysFileUploadFilesBody
*/
isPublic?: boolean;
/**
* .jpeg.jpg.png.bmp.gif.tif
*
* @type {string}
* @memberof SysFileUploadFilesBody
*/
allowSuffix?: string;
/**
* Id
*
* @type {number}
* @memberof SysFileUploadFilesBody
*/
dataId?: number;
/**
* Id
*
* @type {number}
* @memberof SysFileUploadFilesBody
*/
userId?: number;
}

View File

@ -102,6 +102,14 @@ export interface UpdatePosInput {
*/
code?: string | null;
/**
*
*
* @type {string}
* @memberof UpdatePosInput
*/
type?: string | null;
/**
*
*

View File

@ -75,12 +75,4 @@ export interface UploadFileFromBase64Input {
* @memberof UploadFileFromBase64Input
*/
dataId?: number | null;
/**
* Id
*
* @type {number}
* @memberof UploadFileFromBase64Input
*/
userId?: number;
}

View File

@ -1,6 +1,6 @@
<!-- 下拉选择组件支持远程搜索分页自定义查询表单等功能 -->
<script lang="ts" setup>
import { inject, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { useSlots, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { debounce } from 'xe-utils';
const props = defineProps({
@ -16,7 +16,6 @@ const props = defineProps({
* :label-prop="realName"
* :value-prop="id"
* @@change="handelChange"
* allow-create
* filterable
* clearable
* class="w100"
@ -176,6 +175,7 @@ const props = defineProps({
const tableRef = ref();
const selectRef = ref();
const slots = useSlots();
const emit = defineEmits(['update:modelValue', 'change']);
const state = reactive({
selectedValues: '' as string | string[],
@ -260,7 +260,12 @@ const remoteMethod = debounce((query: any) => {
}
}, 800);
const handleQuery = () => {
const handleQuery = (clearKeyword: boolean = false) => {
if (clearKeyword) {
state.tableQuery[props.keywordProp] = undefined;
const input = selectRef.value.$el.querySelector('input');
if (input) input.value = '';
}
remoteMethod(state.tableQuery);
};
@ -291,12 +296,12 @@ const handleChange = (row: any) => {
//
const selectVisibleChange = (visible: boolean) => {
if (!visible) return;
state.tableData.items = [];
state.tableData.total = 0;
state.tableQuery[props.keywordProp] = undefined;
handleQuery();
if (visible) {
state.tableData.items = [];
state.tableData.total = 0;
state.tableQuery = Object.assign({ page: 1 }, props.queryParams) as any;
handleQuery();
}
};
//
@ -333,6 +338,17 @@ const setValue = (option: any | any[], row: any) => {
emit('change', state.selectedValues, row);
};
//
const selectedValuesChange = (val: any) => {
//
emit('update:modelValue', val);
emit(
'change',
val,
state.tableData?.items?.find((item) => item[props.valueProp] === val)
);
};
watch(
() => props.modelValue,
(val: any) => (state.selectedValues = val),
@ -354,6 +370,7 @@ defineExpose({
<template>
<el-select
v-bind="$attrs"
v-model="state.selectedValues"
:clearable="clearable"
:multiple="multiple"
@ -361,6 +378,7 @@ defineExpose({
:placeholder="placeholder"
:remote-method="remoteMethod"
@visible-change="selectVisibleChange"
@change="selectedValuesChange"
:style="{ width: dropdownWidth }"
popper-class="popper-class"
ref="selectRef"
@ -379,7 +397,7 @@ defineExpose({
<el-form :model="state.tableQuery" v-if="$slots.queryForm" class="mg5 query-form" :label-width="queryLabelWidth ?? ''" @click.stop>
<el-row :gutter="10">
<!-- 查询表单插槽内容 -->
<slot name="queryForm" :query="state.tableQuery" :handleQuery="handleQuery"></slot>
<slot name="queryForm" :query="state.tableQuery" :handleQuery="() => handleQuery(true)"></slot>
<!-- 查询和重置按钮 -->
<el-button-group style="position: absolute; right: 10px">
<el-button type="primary" icon="ele-Search" @click="remoteMethod(state.tableQuery)" v-reclick="1000"> 查询 </el-button>

View File

@ -1,14 +1,14 @@
<template>
<el-popover placement="bottom" width="300" trigger="hover">
<template #reference>
<el-text type="primary" class="cursor-pointer">
<el-text type="primary" class="cursor-default">
<el-icon><ele-InfoFilled /></el-icon>{{ t('message.list.detail') }}
</el-text>
</template>
<el-descriptions direction="vertical" :column="2" border>
<el-descriptions-item width="140">
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-UserFilled /></el-icon>{{ t('message.list.creator') }}
</el-text>
</template>
@ -16,7 +16,7 @@
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-Calendar /></el-icon>{{ t('message.list.createTime') }}
</el-text>
</template>
@ -24,7 +24,7 @@
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-UserFilled /></el-icon>{{ t('message.list.modifier') }}
</el-text>
</template>
@ -32,7 +32,7 @@
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-Calendar /></el-icon>{{ t('message.list.modifyTime') }}
</el-text>
</template>
@ -41,7 +41,7 @@
<el-descriptions-item>
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-OfficeBuilding /></el-icon>{{ t('message.list.organizationName') }}
</el-text>
</template>
@ -49,7 +49,7 @@
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-School /></el-icon>{{ t('message.list.tenantName') }}
</el-text>
</template>
@ -58,7 +58,7 @@
<el-descriptions-item v-if="'remark' in props.data">
<template #label>
<el-text>
<el-text truncated class="one-line">
<el-icon><ele-Tickets /></el-icon>{{ t('message.list.remark') }}
</el-text>
</template>
@ -76,3 +76,13 @@ const props = defineProps<{
data: ModifyRecord;
}>();
</script>
<style lang="scss" scoped>
.one-line {
width: 120px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

View File

@ -1,5 +1,6 @@
import type { FormItemRule } from 'element-plus';
import { ElMessage } from 'element-plus';
import { nextTick, Ref, watch } from 'vue';
const TRIGGER_INPUT: FormItemRule['trigger'] = 'change';
const TRIGGER_BLUR: FormItemRule['trigger'] = 'blur';
@ -17,6 +18,27 @@ export function useFormRulePresets() {
trigger,
});
const validatorIf = (shouldError: () => boolean, formRef?: Ref<any>, label: string = '此项') => {
let field = '';
watch(
() => shouldError(),
() => nextTick(() => formRef?.value?.validateField(field).catch(() => {})),
{ immediate: false, deep: true }
);
return {
validator: (_: any, __: any, callback: (error?: Error) => void) => {
field = _.field;
if (shouldError()) {
callback(new Error(`${label}为必填`));
} else {
callback();
}
},
trigger: ['blur', 'change'] as const,
};
};
const maxLen = (len: number, label = '此项', trigger = TRIGGER_INPUT): FormItemRule => ({
max: len,
message: `${label}长度不能超过 ${len} 个字符`,
@ -373,6 +395,7 @@ export function useFormRulePresets() {
return {
required,
requiredIf,
validatorIf,
maxLen,
minLen,
pattern,

View File

@ -95,6 +95,7 @@ import { initBackEndControlRoutes } from '/@/router/backEnd';
import { Local, Session } from '/@/utils/storage';
import { formatAxis } from '/@/utils/formatTime';
import { NextLoading } from '/@/utils/loading';
import { loadSysInfo } from '/@/utils/sysInfo';
import { sm2 } from 'sm-crypto-v2';
import { useRoutesList } from '/@/stores/routesList';
import { useThemeConfig } from '/@/stores/themeConfig';
@ -161,11 +162,9 @@ onMounted(async () => {
const accessToken = route.query.token;
if (accessToken) await saveTokenAndInitRoutes(accessToken);
//
//
if (themeConfig.value.captcha == undefined) {
setTimeout(() => {
window.location.reload();
}, 1000);
await loadSysInfo(Local.get('tid') ?? 0);
}
//

View File

@ -4,7 +4,7 @@
<div class="card-header">
<div class="tree-h-flex">
<div class="tree-h-left">
<el-input :prefix-icon="Search" v-model.lazy="filterText" clearable placeholder="文件名称" />
<el-input :prefix-icon="Search" v-model.lazy="filterText" clearable placeholder="文件路径" />
</div>
<div class="tree-h-right">
<el-dropdown @command="handleCommand">
@ -126,11 +126,22 @@ const handleCommand = async (command: string | number | object) => {
//
const emits = defineEmits(['node-click']);
const nodeClick = (node: any) => {
emits('node-click', { id: node.id, name: node.name });
const nodeClick = (node: any, data: any) => {
var path = node.name;
if (data.level == 4) {
//
var monthNode = treeRef.value!.getNode(node.pid);
var yearNode = treeRef.value!.getNode(monthNode.data.pid);
path = `${yearNode.data.name}/${monthNode.data.name}/${node.name}`;
} else if (data.level == 3) {
//
var yearNode = treeRef.value!.getNode(node.pid);
path = `${yearNode.data.name}/${node.name}`;
}
emits('node-click', { id: node.id, name: node.name, path: path });
};
//
//
const setCurrentKey = (key?: TreeKey | undefined, shouldAutoExpandParent?: boolean | undefined) => {
treeRef.value?.setCurrentKey(key, shouldAutoExpandParent);
};

View File

@ -105,7 +105,7 @@
<el-radio :value="true"></el-radio>
</el-radio-group>
<el-upload ref="uploadRef" drag :auto-upload="false" :limit="1" :file-list="state.fileList" action :on-change="handleChange" accept=".jpg,.png,.bmp,.gif,.txt,.xml,.pdf,.xlsx,.docx">
<el-upload ref="uploadRef" drag :auto-upload="false" :file-list="state.fileList" action :on-change="handleChange" accept=".jpg,.png,.bmp,.gif,.txt,.xml,.pdf,.xlsx,.docx">
<el-icon class="el-icon--upload">
<ele-UploadFilled />
</el-icon>
@ -281,7 +281,11 @@ const handleChange = (file: any, fileList: []) => {
//
const handleUpload = async () => {
if (state.fileList.length < 1) return;
await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, '', state.isPublic);
// //
// await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, '', state.isPublic);
//
var files = state.fileList.map((file: any) => file.raw);
await getAPI(SysFileApi).apiSysFileUploadFilesPostForm(files, state.fileType, '', state.isPublic);
handleQuery();
ElMessage.success('上传成功');
state.visible = false;
@ -332,7 +336,7 @@ const gridEvents: VxeGridListeners<SysFile> = {
//
const handleNodeChange = async (node: any) => {
state.queryParams.fileName = undefined;
state.queryParams.filePath = node.name;
state.queryParams.filePath = node.path;
state.queryParams.startTime = undefined;
state.queryParams.endTime = undefined;
await handleQuery();

View File

@ -140,7 +140,7 @@ const nodeClick = (node: any) => {
emits('node-click', { id: node.id, name: node.name });
};
//
//
const setCurrentKey = (key?: TreeKey | undefined, shouldAutoExpandParent?: boolean | undefined) => {
treeRef.value?.setCurrentKey(key, shouldAutoExpandParent);
};

View File

@ -19,6 +19,11 @@
<el-input v-model="state.ruleForm.code" :placeholder="$t('message.list.positionCode')" clearable />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item :label="$t('message.list.positionType')">
<el-input v-model="state.ruleForm.type" :placeholder="$t('message.list.positionType')" clearable />
</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.orderNo')">
<el-input-number v-model="state.ruleForm.orderNo" :placeholder="$t('message.list.orderNo')" class="w100" />

View File

@ -152,6 +152,7 @@ const options = useVxeTable<PagePosOutput>(
{ field: 'seq', type: 'seq', title: i18n.t('message.list.seq'), width: 60, fixed: 'left' },
{ field: 'name', title: i18n.t('message.list.jobTitle'), minWidth: 200, showOverflow: 'tooltip' },
{ field: 'code', title: i18n.t('message.list.positionCode'), minWidth: 200, showOverflow: 'tooltip' },
{ field: 'type', title: i18n.t('message.list.positionType'), minWidth: 200, showOverflow: 'tooltip' },
{ field: 'userCount', title: i18n.t('message.list.staffCount'), showOverflow: 'tooltip', slots: { default: 'row_userCount' } },
{ field: 'userList', title: i18n.t('message.list.staffDetails'), showOverflow: 'tooltip', slots: { default: 'row_userList' } },
{ field: 'orderNo', title: i18n.t('message.list.orderNo'), width: 80, showOverflow: 'tooltip' },

View File

@ -286,6 +286,8 @@ const state = reactive({
sqlString: 'select * from xxx',
//
queryResult: [] as any,
//
mainConfigId: '1300000000001',
});
// xGrid
@ -349,7 +351,7 @@ const options = useVxeTable<DbColumnOutput>(
//
onMounted(async () => {
//
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseTableListConfigIdGet('1300000000001');
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseTableListConfigIdGet(state.mainConfigId);
res.data.result.forEach((element: any) => {
// zero_
if (!element.name.startsWith('zero_')) {
@ -366,7 +368,7 @@ const onTableChange = async (value: string, selectConfig: { selectedTables: stri
//
const tableInfo = state.dbTables.find((table) => table.name === value);
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(value, '1300000000001');
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(value, state.mainConfigId);
if (res.data.result && Array.isArray(res.data.result)) {
res.data.result.forEach((newColumn: any) => {
const columnWithTableDesc = {
@ -471,7 +473,7 @@ const removeJoinColumn = (index: number, keyIndex: number) => {
const getJoinTableColumns = async (tableName: string, isLeftTable: boolean = true, joinIndex: number) => {
if (tableName) {
try {
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(tableName, '1300000000001');
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(tableName, state.mainConfigId);
const columns = res?.data?.result || [];
// isLeftTable
@ -492,7 +494,7 @@ const getJoinTableColumns = async (tableName: string, isLeftTable: boolean = tru
//
const changeWhereTable = async (condition: any) => {
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(condition.table, '1300000000001');
const res: any = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(condition.table, state.mainConfigId);
condition.columns = res.data.result;
condition.column = undefined;
condition.value = undefined;

View File

@ -71,7 +71,7 @@
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<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-option v-for="d in state.posData" :key="d.id" :label="d.name + '/' + d.type" :value="d.id" />
</el-select>
</el-form-item>
</el-col>
@ -120,7 +120,7 @@
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<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-option v-for="d in state.posData" :key="d.id" :label="d.name + '/' + d.type" :value="d.id" />
</el-select>
</el-form-item>
</el-col>

View File

@ -55,10 +55,10 @@
<el-empty :image-size="200" />
</template>
<template #row_avatar="{ row }">
<el-avatar :src="row.avatar" size="small"> {{ row.nickName?.slice(0, 1) ?? row.realName?.slice(0, 1) }} </el-avatar>
<el-avatar :src="row.avatar" size="small" :style="{ backgroundColor: row.sex == 1 ? '#409EFF' : '#F56C6C' }"> {{ row.nickName?.slice(0, 1) ?? row.realName?.slice(0, 1) }} </el-avatar>
</template>
<template #row_sex="{ row }">
<el-tag v-if="row.sex === 1" type="success"> {{ $t('message.list.male') }} </el-tag>
<el-tag v-if="row.sex === 1" type="primary"> {{ $t('message.list.male') }} </el-tag>
<el-tag v-else-if="row.sex === 2" type="danger"> {{ $t('message.list.female') }} </el-tag>
<el-tag v-else-if="row.sex === 0" type="info"> {{ $t('message.list.unknown') }} </el-tag>