Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714acc0749 | ||
|
|
1d32f4709b | ||
|
|
b96a4adb9f | ||
|
|
0e08a7d102 | ||
|
|
54e5b46dbf | ||
|
|
f266c9a718 | ||
|
|
b02cf986d3 | ||
|
|
44ef55be00 | ||
|
|
70371e92b3 | ||
|
|
803d862513 | ||
|
|
4a093470d5 | ||
|
|
b01765360d | ||
|
|
02ffc18a61 | ||
|
|
0fb410159a | ||
|
|
d2afa84c37 | ||
|
|
672fb84871 | ||
|
|
1e7a9c7abb | ||
|
|
b83c005f28 | ||
|
|
b9a3cfe377 | ||
|
|
be515339fe | ||
|
|
c65952202a | ||
|
|
ab98cf30c1 | ||
|
|
4d914ead0e | ||
|
|
b67c59710b | ||
|
|
24c9ceefde | ||
|
|
e713bcd9b7 | ||
|
|
400aa876df | ||
|
|
07b4b95732 | ||
|
|
94fa69e8ef | ||
|
|
46c9563f33 | ||
|
|
52240ab6a8 | ||
|
|
ea3fa0e0d6 | ||
|
|
6bf4885f85 | ||
|
|
839e400ed1 | ||
|
|
55733f07e8 | ||
|
|
6533020ebc | ||
|
|
710966e098 | ||
|
|
9495589b28 | ||
|
|
e8cbf35abb | ||
|
|
dc38e97296 | ||
|
|
ba693d1e78 | ||
|
|
e8ab6d47eb | ||
|
|
240a607875 | ||
|
|
09c45c4ba4 | ||
|
|
0257fb294a | ||
|
|
1ca05495d8 | ||
|
|
d1108700e0 | ||
|
|
ff4e857128 | ||
|
|
31cf1a82f1 | ||
|
|
0531c2b330 |
@@ -1,12 +1,11 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
|
||||
+14
-3
@@ -1,13 +1,20 @@
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Io = System.IO;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
namespace Infrastructure.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// web层通用数据处理
|
||||
/// </summary>
|
||||
public class BaseController : ControllerBase
|
||||
{
|
||||
public static string TIME_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
|
||||
@@ -61,7 +68,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
throw new CustomException(fileName + "文件不存在");
|
||||
}
|
||||
var stream = Io.File.OpenRead(path); //创建文件流
|
||||
var stream = System.IO.File.OpenRead(path); //创建文件流
|
||||
|
||||
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", HttpUtility.UrlEncode(fileName));
|
||||
@@ -92,6 +99,10 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
|
||||
return new ApiResult((int)resultCode, msg, data);
|
||||
}
|
||||
protected ApiResult Success()
|
||||
{
|
||||
return GetApiResult(ResultCode.SUCCESS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Infrastructure
|
||||
namespace Infrastructure.Converter
|
||||
{
|
||||
public class JsonConverterUtil
|
||||
{
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Infrastructure.Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Json任何类型读取到字符串属性
|
||||
/// 因为 System.Text.Json 必须严格遵守类型一致,当非字符串读取到字符属性时报错:
|
||||
/// The JSON value could not be converted to System.String.
|
||||
/// </summary>
|
||||
public class StringConverter : System.Text.Json.Serialization.JsonConverter<string>
|
||||
{
|
||||
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
return reader.GetString();
|
||||
}
|
||||
else
|
||||
{
|
||||
//非字符类型,返回原生内容
|
||||
return GetRawPropertyValue(reader);
|
||||
}
|
||||
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// 非字符类型,返回原生内容
|
||||
/// </summary>
|
||||
/// <param name="jsonReader"></param>
|
||||
/// <returns></returns>
|
||||
private static string GetRawPropertyValue(Utf8JsonReader jsonReader)
|
||||
{
|
||||
ReadOnlySpan<byte> utf8Bytes = jsonReader.HasValueSequence ?
|
||||
jsonReader.ValueSequence.ToArray() :
|
||||
jsonReader.ValueSpan;
|
||||
return Encoding.UTF8.GetString(utf8Bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,19 @@ namespace Infrastructure
|
||||
public class CustomException : Exception
|
||||
{
|
||||
public int Code { get; set; }
|
||||
/// <summary>
|
||||
/// 前端提示语
|
||||
/// </summary>
|
||||
public string Msg { get; set; }
|
||||
/// <summary>
|
||||
/// 记录到日志的详细内容
|
||||
/// </summary>
|
||||
public string LogMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否通知
|
||||
/// </summary>
|
||||
public bool Notice { get; set; } = true;
|
||||
|
||||
public CustomException(string msg) : base(msg)
|
||||
{
|
||||
}
|
||||
@@ -17,9 +27,10 @@ namespace Infrastructure
|
||||
Msg = msg;
|
||||
}
|
||||
|
||||
public CustomException(ResultCode resultCode, string msg) : base(msg)
|
||||
public CustomException(ResultCode resultCode, string msg, bool notice = true) : base(msg)
|
||||
{
|
||||
Code = (int)resultCode;
|
||||
Notice = notice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -54,5 +54,10 @@
|
||||
/// 清空数据
|
||||
/// </summary>
|
||||
CLEAN = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 下载
|
||||
/// </summary>
|
||||
DOWNLOAD = 10,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Infrastructure
|
||||
|
||||
#region 获取unix时间戳
|
||||
/// <summary>
|
||||
/// 获取unix时间戳
|
||||
/// 获取unix时间戳(毫秒)
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ZR.Common
|
||||
namespace Infrastructure.Helper
|
||||
{
|
||||
public class JnHelper
|
||||
{
|
||||
@@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<Compile Remove="Model\PagedInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspectCore.Abstractions" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,18 +1,19 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System;
|
||||
|
||||
namespace ZR.Admin.WebApi.Framework
|
||||
namespace Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// 2020-11-20
|
||||
/// 2023-8-29已从WebApi移至此
|
||||
/// </summary>
|
||||
public class JwtUtil
|
||||
{
|
||||
@@ -21,7 +22,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <returns></returns>
|
||||
public static LoginUser GetLoginUser(HttpContext httpContext)
|
||||
public static TokenModel GetLoginUser(HttpContext httpContext)
|
||||
{
|
||||
string token = httpContext.GetToken();
|
||||
|
||||
@@ -36,10 +37,12 @@ namespace ZR.Admin.WebApi.Framework
|
||||
/// 生成token
|
||||
/// </summary>
|
||||
/// <param name="claims"></param>
|
||||
/// <param name="jwtSettings"></param>
|
||||
/// <returns></returns>
|
||||
public static string GenerateJwtToken(List<Claim> claims, JwtSettings jwtSettings)
|
||||
public static string GenerateJwtToken(List<Claim> claims)
|
||||
{
|
||||
JwtSettings jwtSettings = new();
|
||||
AppSettings.Bind("JwtSettings", jwtSettings);
|
||||
|
||||
var authTime = DateTime.Now;
|
||||
var expiresAt = authTime.AddMinutes(jwtSettings.Expire);
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
@@ -55,7 +58,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
IssuedAt = authTime,//token生成时间
|
||||
Expires = expiresAt,
|
||||
//NotBefore = authTime,
|
||||
TokenType = "Bearer",
|
||||
TokenType = jwtSettings.TokenType,
|
||||
//对称秘钥,签名证书
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
@@ -96,7 +99,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
/// </summary>
|
||||
/// <param name="token">令牌</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Claim>? ParseToken(string token)
|
||||
public static JwtSecurityToken? ParseToken(string token)
|
||||
{
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var validateParameter = ValidParameters();
|
||||
@@ -105,8 +108,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
{
|
||||
tokenHandler.ValidateToken(token, validateParameter, out SecurityToken validatedToken);
|
||||
|
||||
var jwtToken = tokenHandler.ReadJwtToken(token);
|
||||
return jwtToken.Claims;
|
||||
return tokenHandler.ReadJwtToken(token);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -119,25 +121,21 @@ namespace ZR.Admin.WebApi.Framework
|
||||
/// <summary>
|
||||
/// jwt token校验
|
||||
/// </summary>
|
||||
/// <param name="jwtToken"></param>
|
||||
/// <param name="jwtSecurityToken"></param>
|
||||
/// <returns></returns>
|
||||
public static LoginUser? ValidateJwtToken(IEnumerable<Claim> jwtToken)
|
||||
public static TokenModel? ValidateJwtToken(JwtSecurityToken jwtSecurityToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginUser loginUser = null;
|
||||
|
||||
var userData = jwtToken.FirstOrDefault(x => x.Type == ClaimTypes.UserData)?.Value;
|
||||
if (jwtSecurityToken == null) return null;
|
||||
IEnumerable<Claim> claims = jwtSecurityToken?.Claims;
|
||||
TokenModel loginUser = null;
|
||||
|
||||
var userData = claims.FirstOrDefault(x => x.Type == ClaimTypes.UserData)?.Value;
|
||||
if (userData != null)
|
||||
{
|
||||
loginUser = JsonConvert.DeserializeObject<LoginUser>(userData);
|
||||
var permissions = CacheService.GetUserPerms(GlobalConstant.UserPermKEY + loginUser?.UserId);
|
||||
if (loginUser?.UserName == GlobalConstant.AdminRole)
|
||||
{
|
||||
permissions = new List<string>() { GlobalConstant.AdminPerm };
|
||||
}
|
||||
if (permissions == null) return null;
|
||||
loginUser.Permissions = permissions;
|
||||
loginUser = JsonConvert.DeserializeObject<TokenModel>(userData);
|
||||
loginUser.ExpireTime = jwtSecurityToken.ValidTo;
|
||||
}
|
||||
return loginUser;
|
||||
}
|
||||
@@ -153,7 +151,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Claim> AddClaims(LoginUser user)
|
||||
public static List<Claim> AddClaims(TokenModel user)
|
||||
{
|
||||
var claims = new List<Claim>()
|
||||
{
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
public class Log
|
||||
{
|
||||
public static void WriteLine(ConsoleColor color = ConsoleColor.Black, string msg = "")
|
||||
{
|
||||
Console.ForegroundColor = color;
|
||||
Console.WriteLine($"{DateTime.Now} {msg}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,26 @@
|
||||
using Infrastructure.Constant;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Infrastructure.Model
|
||||
{
|
||||
public class ApiResult
|
||||
public class ApiResult : Dictionary<string, object>
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Msg { get; set; }
|
||||
/** 状态码 */
|
||||
public static readonly string CODE_TAG = "code";
|
||||
|
||||
/** 返回内容 */
|
||||
public static readonly string MSG_TAG = "msg";
|
||||
|
||||
/** 数据对象 */
|
||||
public static readonly string DATA_TAG = "data";
|
||||
//public int Code { get; set; }
|
||||
//public string Msg { get; set; }
|
||||
/// <summary>
|
||||
/// 如果data值为null,则忽略序列化将不会返回data字段
|
||||
/// </summary>
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public object Data { get; set; }
|
||||
//[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
//public object Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化一个新创建的APIResult对象,使其表示一个空消息
|
||||
@@ -27,8 +36,8 @@ namespace Infrastructure.Model
|
||||
/// <param name="msg"></param>
|
||||
public ApiResult(int code, string msg)
|
||||
{
|
||||
Code = code;
|
||||
Msg = msg;
|
||||
Add(CODE_TAG, code);
|
||||
Add(MSG_TAG, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -36,33 +45,28 @@ namespace Infrastructure.Model
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="data"></param>
|
||||
public ApiResult(int code, string msg, object data)
|
||||
{
|
||||
Code = code;
|
||||
Msg = msg;
|
||||
Add(CODE_TAG, code);
|
||||
Add(MSG_TAG, msg);
|
||||
if (data != null)
|
||||
{
|
||||
Data = data;
|
||||
Add(DATA_TAG, data);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回成功消息
|
||||
/// </summary>
|
||||
/// < returns > 成功消息 </ returns >
|
||||
public static ApiResult Success() { return new ApiResult(HttpStatus.SUCCESS, "success"); }
|
||||
|
||||
/// <summary>
|
||||
/// 返回成功消息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ApiResult Success()
|
||||
{
|
||||
Code = (int)ResultCode.SUCCESS;
|
||||
Msg = "success";
|
||||
return this;
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 返回成功消息
|
||||
///// </summary>
|
||||
///// <param name = "data" > 数据对象 </ param >
|
||||
///// < returns > 成功消息 </ returns >
|
||||
//public static ApiResult Success(object data) { return new ApiResult(HttpStatus.SUCCESS, "success", data); }
|
||||
/// <param name="data"></param>
|
||||
/// <returns> 成功消息 </returns >
|
||||
public static ApiResult Success(object data) { return new ApiResult(HttpStatus.SUCCESS, "success", data); }
|
||||
|
||||
/// <summary>
|
||||
/// 返回成功消息
|
||||
@@ -79,21 +83,9 @@ namespace Infrastructure.Model
|
||||
/// <returns>成功消息</returns>
|
||||
public static ApiResult Success(string msg, object data) { return new ApiResult(HttpStatus.SUCCESS, msg, data); }
|
||||
|
||||
/// <summary>
|
||||
/// 访问被拒
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ApiResult On401()
|
||||
public static ApiResult Error(ResultCode code, string msg = "")
|
||||
{
|
||||
Code = (int)ResultCode.DENY;
|
||||
Msg = "access denyed";
|
||||
return this;
|
||||
}
|
||||
public ApiResult Error(ResultCode resultCode, string msg = "")
|
||||
{
|
||||
Code = (int)resultCode;
|
||||
Msg = msg;
|
||||
return this;
|
||||
return Error((int)code, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,9 +103,26 @@ namespace Infrastructure.Model
|
||||
/// <returns></returns>
|
||||
public static ApiResult Error(string msg) { return new ApiResult((int)ResultCode.CUSTOM_ERROR, msg); }
|
||||
|
||||
public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// 是否为成功消息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsSuccess()
|
||||
{
|
||||
return $"msg={Msg},data={Data}";
|
||||
return HttpStatus.SUCCESS == (int)this[CODE_TAG];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 方便链式调用
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public ApiResult Put(string key, object value)
|
||||
{
|
||||
Add(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Infrastructure
|
||||
namespace Infrastructure.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取配置文件POCO实体类
|
||||
/// </summary>
|
||||
public class OptionsSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否单点登录
|
||||
/// </summary>
|
||||
public bool SingleLogin { get; set; }
|
||||
/// <summary>
|
||||
/// 是否演示模式
|
||||
/// </summary>
|
||||
public bool DemoMode { get; set; }
|
||||
/// <summary>
|
||||
/// 初始化db
|
||||
/// </summary>
|
||||
public bool InitDb { get; set; }
|
||||
public MailOptions MailOptions { get; set; }
|
||||
public Upload Upload { get; set; }
|
||||
public ALIYUN_OSS ALIYUN_OSS { get; set; }
|
||||
@@ -78,6 +84,14 @@ namespace Infrastructure
|
||||
/// token时间(分)
|
||||
/// </summary>
|
||||
public int Expire { get; set; } = 1440;
|
||||
/// <summary>
|
||||
/// 刷新token时长
|
||||
/// </summary>
|
||||
public int RefreshTokenTime { get; set; }
|
||||
/// <summary>
|
||||
/// token类型
|
||||
/// </summary>
|
||||
public string TokenType { get; set; } = "Bearer";
|
||||
}
|
||||
|
||||
public class Gen
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Infrastructure.Model
|
||||
{
|
||||
public class TokenModel
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long DeptId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
/// <summary>
|
||||
/// 角色集合
|
||||
/// </summary>
|
||||
public List<string> RoleIds { get; set; }
|
||||
/// <summary>
|
||||
/// 角色集合(数据权限过滤使用)
|
||||
/// </summary>
|
||||
public List<Roles> Roles { get; set; }
|
||||
/// <summary>
|
||||
/// Jwt过期时间
|
||||
/// </summary>
|
||||
public DateTime ExpireTime { get; set; }
|
||||
/// <summary>
|
||||
/// 权限集合
|
||||
/// </summary>
|
||||
//public List<string> Permissions { get; set; } = new List<string>();
|
||||
public TokenModel()
|
||||
{
|
||||
}
|
||||
|
||||
public TokenModel(TokenModel info, List<Roles> roles)
|
||||
{
|
||||
UserId = info.UserId;
|
||||
UserName = info.UserName;
|
||||
DeptId = info.DeptId;
|
||||
Roles = roles;
|
||||
RoleIds = roles.Select(f => f.RoleKey).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public class Roles
|
||||
{
|
||||
public long RoleId { get; set; }
|
||||
public string RoleKey { get; set; }
|
||||
public int DataScope { get; set; }
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -1,8 +1,10 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Attribute;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
namespace Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// App服务注册
|
||||
+8
-1
@@ -1,5 +1,12 @@
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// 跨域扩展
|
||||
/// </summary>
|
||||
public static class CorsExtension
|
||||
{
|
||||
/// <summary>
|
||||
+6
-3
@@ -1,14 +1,17 @@
|
||||
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
namespace Infrastructure
|
||||
{
|
||||
public static class EntityExtension
|
||||
{
|
||||
public static TSource ToCreate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null) return source;
|
||||
if (types == null || context == null) return source;
|
||||
BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
|
||||
|
||||
types.GetProperty("CreateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||
@@ -23,7 +26,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
public static TSource ToUpdate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null) return source;
|
||||
if (types == null || context == null) return source;
|
||||
BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
|
||||
|
||||
types.GetProperty("UpdateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||
+41
-31
@@ -1,12 +1,15 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using UAParser;
|
||||
using ZR.Model.System;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
namespace Infrastructure.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// HttpContext扩展类
|
||||
@@ -50,7 +53,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
if (result.Contains("::1"))
|
||||
result = "127.0.0.1";
|
||||
|
||||
result = result.Replace("::ffff:", "127.0.0.1");
|
||||
result = result.Replace("::ffff:", "");
|
||||
result = result.Split(':')?.FirstOrDefault() ?? "127.0.0.1";
|
||||
result = IsIP(result) ? result : "127.0.0.1";
|
||||
return result;
|
||||
@@ -82,7 +85,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetName(this HttpContext context)
|
||||
public static string GetName(this HttpContext context)
|
||||
{
|
||||
var uid = context.User?.Identity?.Name;
|
||||
|
||||
@@ -105,7 +108,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<ClaimsIdentity>? GetClaims(this HttpContext context)
|
||||
public static IEnumerable<ClaimsIdentity> GetClaims(this HttpContext context)
|
||||
{
|
||||
return context.User?.Identities;
|
||||
}
|
||||
@@ -131,26 +134,12 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
return context.Request.Headers["Authorization"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static ClientInfo GetClientInfo(this HttpContext context)
|
||||
{
|
||||
var str = context.GetUserAgent();
|
||||
var uaParser = Parser.GetDefault();
|
||||
ClientInfo c = uaParser.Parse(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求Url
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetRequestUrl(this HttpContext context)
|
||||
public static string GetRequestUrl(this HttpContext context)
|
||||
{
|
||||
return context != null ? context.Request.Path.Value : "";
|
||||
}
|
||||
@@ -194,30 +183,51 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
return body;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static ClientInfo GetClientInfo(this HttpContext context)
|
||||
{
|
||||
var str = context.GetUserAgent();
|
||||
var uaParser = Parser.GetDefault();
|
||||
ClientInfo c = uaParser.Parse(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据IP获取地理位置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetIpInfo(string IP)
|
||||
{
|
||||
var ipInfo = IpTool.Search(IP);
|
||||
return ipInfo?.Province + "-" + ipInfo?.City + "-" + ipInfo?.NetworkOperator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置请求参数
|
||||
/// </summary>
|
||||
/// <param name="operLog"></param>
|
||||
/// <param name="reqMethod"></param>
|
||||
/// <param name="context"></param>
|
||||
public static void GetRequestValue(this HttpContext context, SysOperLog operLog)
|
||||
public static string GetRequestValue(this HttpContext context, string reqMethod)
|
||||
{
|
||||
string reqMethod = operLog.RequestMethod;
|
||||
string param= string.Empty;
|
||||
string param = string.Empty;
|
||||
|
||||
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod) || HttpMethods.IsDelete(reqMethod))
|
||||
{
|
||||
param = context.GetBody();
|
||||
param = PwdRep().Replace(param, "***");
|
||||
string regex = "(?<=\"password\":\")[^\",]*";
|
||||
param = Regex.Replace(param, regex, "***");
|
||||
}
|
||||
if (param.IsEmpty())
|
||||
{
|
||||
param = context.GetQueryString();
|
||||
}
|
||||
operLog.OperParam = param;
|
||||
return param;
|
||||
}
|
||||
|
||||
[GeneratedRegex("(?<=\"password\":\")[^\",]*")]
|
||||
private static partial Regex PwdRep();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
using AspNetCoreRateLimit;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
namespace ZR.Infrastructure.WebExtensions
|
||||
{
|
||||
public static class IPRateExtension
|
||||
{
|
||||
@@ -0,0 +1,39 @@
|
||||
using Infrastructure;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZR.Infrastructure.WebExtensions
|
||||
{
|
||||
public static class JwtExtension
|
||||
{
|
||||
public static void AddJwt(this IServiceCollection services)
|
||||
{
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
}).AddCookie()
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
o.TokenValidationParameters = JwtUtil.ValidParameters();
|
||||
o.Events = new JwtBearerEvents
|
||||
{
|
||||
OnAuthenticationFailed = context =>
|
||||
{
|
||||
// 如果过期,把过期信息添加到头部
|
||||
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
|
||||
{
|
||||
Console.WriteLine("jwt过期了");
|
||||
context.Response.Headers.Add("Token-Expired", "true");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -1,7 +1,9 @@
|
||||
using JinianNet.JNTemplate;
|
||||
using ZR.Common;
|
||||
using Infrastructure.Helper;
|
||||
using JinianNet.JNTemplate;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
namespace Infrastructure
|
||||
{
|
||||
public static class LogoExtension
|
||||
{
|
||||
@@ -10,13 +12,14 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
var contentTpl = JnHelper.ReadTemplate("", "logo.txt");
|
||||
var content = contentTpl?.Render();
|
||||
|
||||
var context = App.HttpContext;
|
||||
Console.WriteLine(content);
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
Console.WriteLine("🎉源码地址: https://gitee.com/izory/ZrAdminNetCore");
|
||||
Console.WriteLine("📖官方文档:http://www.izhaorui.cn/doc");
|
||||
Console.WriteLine("🤑打赏作者:http://www.izhaorui.cn/doc/support.html");
|
||||
Console.WriteLine("💰打赏作者:http://www.izhaorui.cn/doc/support.html");
|
||||
Console.WriteLine("📱移动端体验:http://www.izhaorui.cn/h5");
|
||||
Console.WriteLine($"Swagger地址:[后端启动地址]/swagger/index.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>8632</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspectCore.Abstractions" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.7" />
|
||||
<PackageReference Include="JinianNet.JNTemplate" Version="2.3.3" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.2" />
|
||||
<PackageReference Include="CSRedisCore" Version="3.8.670" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+4
-7
@@ -22,10 +22,6 @@
|
||||
-Based on. NET5/. A common rights management platform (RBAC model) implemented by NET7. Integrate the latest technology for efficient and rapid development, front-end and back-end separation mode, out of the box.
|
||||
- Less code, simple to learn, easy to understand, powerful, easy to extend, lightweight, make web development faster, simpler and more efficient (say goodbye to 996), solve 70% of repetitive work, focus on your business, easy development from now on!
|
||||
- 提供了技术栈(Ant Design Vue)版[Ant Design Vue](https://gitee.com/billzh/mc-dull.git)
|
||||
- 七牛云通用云产品优惠券:[点我进入](https://s.qiniu.com/FzEfay)。
|
||||
- 腾讯云秒杀场:[☛☛ 点我进入 ☚☚](https://curl.qcloud.com/4yEoRquq)。
|
||||
- 腾讯云优惠券:[☛☛ 点我领取 ☚☚](https://curl.qcloud.com/5J4nag8D)。
|
||||
- 阿里云特惠专区:[☛☛ 点我进入 ☚☚](https://www.aliyun.com/minisite/goods?userCode=uotn5vt1&share_source=copy_link)
|
||||
|
||||
```
|
||||
If it helps you, you can click "Star" in the upper right corner to collect it, so that the author has the motivation to continue to go on for free, thank you! ~
|
||||
@@ -52,7 +48,7 @@ Since it is a personal project, the funds are limited, and the experience server
|
||||
|
||||
| repository | Github | Gitee |
|
||||
| -------------- | ------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| Net7 | [Clone/Download](https://github.com/izhaorui/Zr.Admin.NET) | [Clone/Download](https://gitee.com/izory/ZrAdminNetCore/tree/net7.0/) |
|
||||
| Net7 | [Clone/Download](https://github.com/izhaorui/Zr.Admin.NET) | [Clone/Download](https://gitee.com/izory/ZrAdminNetCore) |
|
||||
| Vue3(Hot) | [Clone/Download](https://github.com/izhaorui/ZR.Admin.Vue3) | [Clone/Download](https://gitee.com/izory/ZRAdmin-vue) |
|
||||
|
||||
## 🍁 Front-end technology
|
||||
@@ -61,7 +57,7 @@ Vue Front-end technology stack: Based on Vue2.x/Vue3.x/UniApp, Vue, Vue-router,
|
||||
|
||||
## 🍀 Back-end technology
|
||||
|
||||
- Core Framework: . Net5.0/. Net7.0 + Web API + sqlsugar + swagger + signalR + IpRateLimit + Quartz.net + Redis
|
||||
- Core Framework: . Net7.0 + Web API + sqlsugar + swagger + signalR + IpRateLimit + Quartz.net + Redis
|
||||
- Scheduled tasks: Quartz.Net component that supports the execution of assemblies or HTTP network requests
|
||||
- Security support: filters (data permission filtering), SQL injection, request forgery
|
||||
- Log management: NLog, login log, operation log, scheduled task log
|
||||
@@ -99,7 +95,8 @@ Vue Front-end technology stack: Based on Vue2.x/Vue3.x/UniApp, Vue, Vue-router,
|
||||
## 🍻 Project structure
|
||||
|
||||
```
|
||||
├─ZR.Service ->[服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Service ->[你的业务服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.ServiceCore ->[系统服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Repository ->[仓库层类库]:方便提供有执行存储过程的操作;
|
||||
├─ZR.Model ->[实体层类库]:提供项目中的数据库表、数据传输对象;
|
||||
├─ZR.Admin.WebApi ->[webapi接口]:为Vue版或其他三方系统提供接口服务。
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<a href="https://gitee.com/izory/ZrAdminNetCore"><img src="https://gitee.com/izory/ZrAdminNetCore/badge/star.svg?theme=dark"></a>
|
||||
<a href='https://gitee.com/izory/ZrAdminNetCore/members'><img src='https://gitee.com/izory/ZrAdminNetCore/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||
<a href="https://gitee.com/izory/ZrAdminNetCore/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||
<a href="http://www.izhaorui.cn/doc/changelog.html"><img src="https://img.shields.io/badge/更新日志-20230713-yellow"/></a>
|
||||
<a href="http://www.izhaorui.cn/doc/changelog.html"><img src="https://img.shields.io/badge/更新日志-20230811-yellow"/></a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -28,7 +28,7 @@
|
||||
- 阿里云特惠专区:[☛☛ 点我进入 ☚☚](https://www.aliyun.com/minisite/goods?userCode=uotn5vt1&share_source=copy_link)
|
||||
|
||||
```
|
||||
如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,这样作者才有继续免费下去的动力,谢谢!~
|
||||
如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,谢谢!~
|
||||
```
|
||||
|
||||
## 🍿 在线体验
|
||||
@@ -38,7 +38,7 @@
|
||||
- Vue3.x 版本体验:[http://www.izhaorui.cn/vue3](http://www.izhaorui.cn/vue3)
|
||||
- Vue2.x 版本体验:[http://www.izhaorui.cn/admin](http://www.izhaorui.cn/admin)
|
||||
- Uniapp 版本体验:[http://www.izhaorui.cn/h5](http://www.izhaorui.cn/h5)
|
||||
- 账号密码:admin/123456
|
||||
- 账号密码:admin/123456,普通用户 user/123456
|
||||
|
||||
| H5 | 微信小程序 |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
| 仓库 | Github | Gitee |
|
||||
| -------------- | ------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| Net7 | [克隆/下载](https://github.com/izhaorui/Zr.Admin.NET) | [克隆/下载](https://gitee.com/izory/ZrAdminNetCore/tree/net7.0/) |
|
||||
| Net7 | [克隆/下载](https://github.com/izhaorui/Zr.Admin.NET) | [克隆/下载](https://gitee.com/izory/ZrAdminNetCore) |
|
||||
| Vue3(推荐使用) | [克隆/下载](https://github.com/izhaorui/ZR.Admin.Vue3) | [克隆/下载](https://gitee.com/izory/ZRAdmin-vue) |
|
||||
|
||||
## 🍁 前端技术
|
||||
@@ -72,6 +72,7 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x/uniapp、vuex、vue-router 、vue
|
||||
- 分库分表:使用 orm sqlsugar 可以很轻松的实现分库分库性能优越
|
||||
- 多 租 户:支持多租户功能
|
||||
- 缓存数据:内置内存缓存和 Redis
|
||||
- signalR:使用signalr管理用户在线状态
|
||||
|
||||
## 🍖 内置功能
|
||||
|
||||
@@ -88,18 +89,24 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x/uniapp、vuex、vue-router 、vue
|
||||
11. 在线构建器:拖动表单元素生成相应的 VUE 代码(仅支持 vue2)。
|
||||
12. 任务系统:基于 Quartz.NET,可以在线(添加、修改、删除、手动执行)任务调度包含执行结果日志。
|
||||
13. 文章管理:可以写文章记录。
|
||||
14. 代码生成:可以一键生成前后端代码(.cs、.vue、.js、.sql 等)支持下载,自定义配置前端展示控件、让开发更快捷高效(史上最强)。
|
||||
14. 代码生成:可以一键生成前后端代码(.cs、.vue、.js、.sql、uniapp 等)支持下载,自定义配置前端展示控件、让开发更快捷高效(史上最强)。
|
||||
15. 参数管理:对系统动态配置常用参数。
|
||||
16. 发送邮件:可以对多个用户进行发送邮件。
|
||||
17. 文件管理:可以进行上传文件管理,目前支持上传到本地、阿里云。
|
||||
18. 通知管理:系统通知公告信息发布维护,使用 signalr 实现对用户实时通知。
|
||||
19. 账号注册:可以注册账号登录系统。
|
||||
20. 多语言管理:支持静态、后端动态配置国际化。目前只支持中、英、繁体(仅支持 vue3)
|
||||
21. 在线用户:可以查看正在登录使用的用户,可以对其踢出、通知操作
|
||||
22. db 审计日志:数据库审计功能
|
||||
23. 三方登录:提供三方登录实现逻辑
|
||||
|
||||
## 🍻 项目结构
|
||||
|
||||

|
||||
|
||||
```
|
||||
├─ZR.Service ->[服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Service ->[你的业务服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.ServiceCore ->[系统服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Repository ->[仓库层类库]:方便提供有执行存储过程的操作;
|
||||
├─ZR.Model ->[实体层类库]:提供项目中的数据库表、数据传输对象;
|
||||
├─ZR.Admin.WebApi ->[webapi接口]:为Vue版或其他三方系统提供接口服务。
|
||||
@@ -195,6 +202,7 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x/uniapp、vuex、vue-router 、vue
|
||||
- 👉SqlSugar:[SqlSugar](https://gitee.com/dotnetchina/SqlSugar)
|
||||
- 👉vue-element-admin:[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||
- 👉Meiam.System:[Meiam.System](https://github.com/91270/Meiam.System)
|
||||
- 👉Furion:[Furion](https://gitee.com/dotnetchina/Furion)
|
||||
|
||||
## 🎀 捐赠
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.IService;
|
||||
using ZR.Service.System;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
@@ -14,6 +13,8 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// 公共模块
|
||||
/// </summary>
|
||||
[Route("[controller]/[action]")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
//[Produces("application/json")]
|
||||
public class CommonController : BaseController
|
||||
{
|
||||
private OptionsSetting OptionsSetting;
|
||||
@@ -21,18 +22,22 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
|
||||
private IWebHostEnvironment WebHostEnvironment;
|
||||
private ISysFileService SysFileService;
|
||||
private IHelloService HelloService;
|
||||
|
||||
public CommonController(
|
||||
IOptions<OptionsSetting> options,
|
||||
IWebHostEnvironment webHostEnvironment,
|
||||
ISysFileService fileService)
|
||||
ISysFileService fileService,
|
||||
IHelloService helloService)
|
||||
{
|
||||
WebHostEnvironment = webHostEnvironment;
|
||||
SysFileService = fileService;
|
||||
OptionsSetting = options.Value;
|
||||
HelloService = helloService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// hello
|
||||
/// home
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Route("/")]
|
||||
@@ -43,6 +48,18 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
"如果觉得项目有用,打赏作者喝杯咖啡作为奖励\n☛☛http://www.izhaorui.cn/doc/support.html\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// hello
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
[Route("/hello")]
|
||||
[HttpGet]
|
||||
public IActionResult Hello(string name)
|
||||
{
|
||||
return Ok(HelloService.SayHello(name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 企业消息测试
|
||||
/// </summary>
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// 文章目录Controller
|
||||
/// </summary>
|
||||
[Route("article/ArticleCategory")]
|
||||
[ApiExplorerSettings(GroupName = "article")]
|
||||
public class ArticleCategoryController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@@ -59,7 +60,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
public IActionResult GetArticleCategory(int CategoryId)
|
||||
{
|
||||
var response = _ArticleCategoryService.GetFirst(x => x.CategoryId == CategoryId);
|
||||
|
||||
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("article")]
|
||||
[ApiExplorerSettings(GroupName = "article")]
|
||||
public class ArticleController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@@ -32,7 +33,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("list")]
|
||||
[ActionPermissionFilter(Permission = "system:article:list")]
|
||||
[ActionPermissionFilter(RolePermi = "admin")]
|
||||
public IActionResult Query([FromQuery] ArticleQueryDto parm)
|
||||
{
|
||||
var response = _ArticleService.GetList(parm);
|
||||
@@ -87,7 +88,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
var model = response.Adapt<ArticleDto>();
|
||||
if (model.IsPublic == 0 && userId != model.UserId)
|
||||
{
|
||||
return ToResponse(Infrastructure.ResultCode.CUSTOM_ERROR, "访问失败");
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, "访问失败");
|
||||
}
|
||||
if (model != null)
|
||||
{
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.CodeGenerator;
|
||||
using ZR.CodeGenerator.Model;
|
||||
using ZR.CodeGenerator.Service;
|
||||
using ZR.Common;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Model.System.Generate;
|
||||
@@ -23,6 +17,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("tool/gen")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class CodeGeneratorController : BaseController
|
||||
{
|
||||
private readonly CodeGeneraterService _CodeGeneraterService = new CodeGeneraterService();
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/CommonLang")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class CommonLangController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/config")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysConfigController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@@ -13,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/dept")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysDeptController : BaseController
|
||||
{
|
||||
public ISysDeptService DeptService;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
@@ -13,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/dict/data")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysDictDataController : BaseController
|
||||
{
|
||||
private readonly ISysDictDataService SysDictDataService;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/dict/type")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysDictTypeController : BaseController
|
||||
{
|
||||
private readonly ISysDictService SysDictService;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
@@ -16,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("tool/file")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysFileController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@@ -37,15 +34,13 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
[ActionPermissionFilter(Permission = "tool:file:list")]
|
||||
public IActionResult QuerySysFile([FromQuery] SysFileQueryDto parm)
|
||||
{
|
||||
//开始拼装查询条件
|
||||
var predicate = Expressionable.Create<SysFile>();
|
||||
//搜索条件查询语法参考Sqlsugar
|
||||
|
||||
predicate = predicate.AndIF(parm.BeginCreate_time != null, it => it.Create_time >= parm.BeginCreate_time);
|
||||
predicate = predicate.AndIF(parm.EndCreate_time != null, it => it.Create_time <= parm.EndCreate_time);
|
||||
predicate = predicate.AndIF(parm.StoreType != null, m => m.StoreType == parm.StoreType);
|
||||
predicate = predicate.AndIF(parm.FileId != null, m => m.Id == parm.FileId);
|
||||
|
||||
//搜索条件查询语法参考Sqlsugar
|
||||
var response = _SysFileService.GetPages(predicate.ToExpression(), parm, x => x.Id, OrderByType.Desc);
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using IPTools.Core;
|
||||
using Lazy.Captcha.Core;
|
||||
using Lazy.Captcha.Core;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using UAParser;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Admin.WebApi.Framework;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System;
|
||||
@@ -16,9 +12,10 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <summary>
|
||||
/// 登录
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysLoginController : BaseController
|
||||
{
|
||||
static readonly NLog.Logger logger = NLog.LogManager.GetLogger("LoginController");
|
||||
//static readonly NLog.Logger logger = NLog.LogManager.GetLogger("LoginController");
|
||||
private readonly IHttpContextAccessor httpContextAccessor;
|
||||
private readonly ISysUserService sysUserService;
|
||||
private readonly ISysMenuService sysMenuService;
|
||||
@@ -27,7 +24,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
private readonly ICaptcha SecurityCodeHelper;
|
||||
private readonly ISysConfigService sysConfigService;
|
||||
private readonly ISysRoleService roleService;
|
||||
private readonly OptionsSetting jwtSettings;
|
||||
private readonly OptionsSetting optionSettings;
|
||||
|
||||
public SysLoginController(
|
||||
IHttpContextAccessor contextAccessor,
|
||||
@@ -38,7 +35,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
ISysConfigService configService,
|
||||
ISysRoleService sysRoleService,
|
||||
ICaptcha captcha,
|
||||
IOptions<OptionsSetting> jwtSettings)
|
||||
IOptions<OptionsSetting> optionSettings)
|
||||
{
|
||||
httpContextAccessor = contextAccessor;
|
||||
SecurityCodeHelper = captcha;
|
||||
@@ -48,7 +45,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
this.permissionService = permissionService;
|
||||
this.sysConfigService = configService;
|
||||
roleService = sysRoleService;
|
||||
this.jwtSettings = jwtSettings.Value;
|
||||
this.optionSettings = optionSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,15 +67,17 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
|
||||
}
|
||||
|
||||
var user = sysLoginService.Login(loginBody, RecordLogInfo(httpContextAccessor.HttpContext));
|
||||
sysLoginService.CheckLockUser(loginBody.Username);
|
||||
string location = HttpContextExtension.GetIpInfo(loginBody.LoginIP);
|
||||
var user = sysLoginService.Login(loginBody, new SysLogininfor() { LoginLocation = location });
|
||||
|
||||
List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
|
||||
//权限集合 eg *:*:*,system:user:list
|
||||
List<string> permissions = permissionService.GetMenuPermission(user);
|
||||
|
||||
LoginUser loginUser = new(user, roles, permissions);
|
||||
TokenModel loginUser = new(user.Adapt<TokenModel>(), roles.Adapt<List<Roles>>());
|
||||
CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.UserId, permissions);
|
||||
return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser), jwtSettings.JwtSettings));
|
||||
return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -118,6 +117,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
//权限集合 eg *:*:*,system:user:list
|
||||
List<string> permissions = permissionService.GetMenuPermission(user);
|
||||
user.WelcomeContent = GlobalConstant.WelcomeMessages[new Random().Next(0, GlobalConstant.WelcomeMessages.Length)];
|
||||
|
||||
return SUCCESS(new { user, roles, permissions });
|
||||
}
|
||||
|
||||
@@ -152,28 +152,6 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
return SUCCESS(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录用户登陆信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public SysLogininfor RecordLogInfo(HttpContext context)
|
||||
{
|
||||
var ipAddr = context.GetClientUserIp();
|
||||
var ip_info = IpTool.Search(ipAddr);
|
||||
ClientInfo clientInfo = context.GetClientInfo();
|
||||
SysLogininfor sysLogininfor = new()
|
||||
{
|
||||
Browser = clientInfo.ToString(),
|
||||
Os = clientInfo.OS.ToString(),
|
||||
Ipaddr = ipAddr,
|
||||
UserName = context.GetName(),
|
||||
LoginLocation = ip_info?.Province + "-" + ip_info?.City
|
||||
};
|
||||
|
||||
return sysLogininfor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册
|
||||
/// </summary>
|
||||
@@ -181,7 +159,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <returns></returns>
|
||||
[HttpPost("/register")]
|
||||
[AllowAnonymous]
|
||||
[Log(Title = "注册", BusinessType = Infrastructure.Enums.BusinessType.INSERT)]
|
||||
[Log(Title = "注册", BusinessType = BusinessType.INSERT)]
|
||||
public IActionResult Register([FromBody] RegisterDto dto)
|
||||
{
|
||||
SysConfig config = sysConfigService.GetSysConfigByKey("sys.account.register");
|
||||
@@ -194,7 +172,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
|
||||
}
|
||||
|
||||
|
||||
SysUser user = sysUserService.Register(dto);
|
||||
if (user.UserId > 0)
|
||||
{
|
||||
@@ -202,5 +180,86 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
}
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员");
|
||||
}
|
||||
|
||||
#region 二维码登录
|
||||
|
||||
/// <summary>
|
||||
/// 生成二维码
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="deviceId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/GenerateQrcode")]
|
||||
public IActionResult GenerateQrcode(string uuid, string deviceId)
|
||||
{
|
||||
var state = Guid.NewGuid().ToString();
|
||||
var dict = new Dictionary<string, object>
|
||||
{
|
||||
{ "state", state }
|
||||
};
|
||||
CacheService.SetScanLogin(uuid, dict);
|
||||
return SUCCESS(new
|
||||
{
|
||||
status = 1,
|
||||
state,
|
||||
uuid,
|
||||
codeContent = new { uuid, deviceId }// "https://qm.qq.com/cgi-bin/qm/qr?k=kgt4HsckdljU0VM-0kxND6d_igmfuPlL&authKey=r55YUbruiKQ5iwC/folG7KLCmZ++Y4rQVgNlvLbUniUMkbk24Y9+zNuOmOnjAjRc&noverify=0"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询判断扫码状态
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/VerifyScan")]
|
||||
[AllowAnonymous]
|
||||
public IActionResult VerifyScan([FromBody] ScanDto dto)
|
||||
{
|
||||
int status = -1;
|
||||
object token = string.Empty;
|
||||
if (CacheService.GetScanLogin(dto.Uuid) is Dictionary<string, object> str)
|
||||
{
|
||||
status = 0;
|
||||
str.TryGetValue("token", out token);
|
||||
if (str.ContainsKey("status") && (string)str.GetValueOrDefault("status") == "success")
|
||||
{
|
||||
status = 2;//扫码成功
|
||||
CacheService.RemoveScanLogin(dto.Uuid);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS(new { status, token });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移动端扫码登录
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/ScanLogin")]
|
||||
[Log(Title = "扫码登录")]
|
||||
[Verify]
|
||||
public IActionResult ScanLogin([FromBody] ScanDto dto)
|
||||
{
|
||||
if (dto == null) { return ToResponse(ResultCode.CUSTOM_ERROR, "扫码失败"); }
|
||||
var name = App.HttpContext.GetName();
|
||||
|
||||
sysLoginService.CheckLockUser(name);
|
||||
|
||||
TokenModel tokenModel = JwtUtil.GetLoginUser(HttpContext);
|
||||
if (CacheService.GetScanLogin(dto.Uuid) is not null)
|
||||
{
|
||||
Dictionary<string, object> dict = new() { };
|
||||
dict.Add("status", "success");
|
||||
dict.Add("token", JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(tokenModel)));
|
||||
CacheService.SetScanLogin(dto.Uuid, dict);
|
||||
|
||||
return SUCCESS(1);
|
||||
}
|
||||
return ToResponse(ResultCode.FAIL, "二维码已失效");
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@@ -12,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/system/menu")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysMenuController : BaseController
|
||||
{
|
||||
private readonly ISysRoleService sysRoleService;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
using Infrastructure.Constant;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Admin.WebApi.Hubs;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
using ZR.ServiceCore.Signalr;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
@@ -17,6 +15,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/notice")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysNoticeController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
@@ -14,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/post")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysPostController : BaseController
|
||||
{
|
||||
private readonly ISysPostService PostService;
|
||||
@@ -68,7 +67,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
throw new CustomException($"修改岗位{post.PostName}失败,岗位编码已存在");
|
||||
}
|
||||
post.ToCreate(HttpContext);
|
||||
|
||||
|
||||
return ToResponse(PostService.Add(post));
|
||||
}
|
||||
|
||||
@@ -122,7 +121,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// 岗位导出
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Log(BusinessType = BusinessType.EXPORT, IsSaveResponseData = false, Title= "岗位导出")]
|
||||
[Log(BusinessType = BusinessType.EXPORT, IsSaveResponseData = false, Title = "岗位导出")]
|
||||
[HttpGet("export")]
|
||||
[ActionPermissionFilter(Permission = "system:post:export")]
|
||||
public IActionResult Export()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@@ -12,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/user/profile")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysProfileController : BaseController
|
||||
{
|
||||
private readonly ISysUserService UserService;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
@@ -13,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/role")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysRoleController : BaseController
|
||||
{
|
||||
private readonly ISysRoleService sysRoleService;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
@@ -15,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/user")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysUserController : BaseController
|
||||
{
|
||||
private readonly ISysUserService UserService;
|
||||
@@ -93,9 +93,10 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
}
|
||||
|
||||
user.Create_by = HttpContext.GetName();
|
||||
user.Create_time = DateTime.Now;
|
||||
user.Password = NETCore.Encrypt.EncryptProvider.Md5(user.Password);
|
||||
|
||||
return ToResponse(UserService.InsertUser(user));
|
||||
return SUCCESS(UserService.InsertUser(user));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -143,7 +144,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
public IActionResult Remove(int userid = 0)
|
||||
{
|
||||
if (userid <= 0) { return ToResponse(ApiResult.Error(101, "请求参数错误")); }
|
||||
if (userid == 1) return ToResponse(Infrastructure.ResultCode.FAIL, "不能删除管理员账号");
|
||||
if (userid == 1) return ToResponse(ResultCode.FAIL, "不能删除管理员账号");
|
||||
int result = UserService.DeleteUser(userid);
|
||||
|
||||
return ToResponse(result);
|
||||
@@ -156,7 +157,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
[HttpPut("resetPwd")]
|
||||
[Log(Title = "重置密码", BusinessType = BusinessType.UPDATE)]
|
||||
[ActionPermissionFilter(Permission = "system:user:resetPwd")]
|
||||
public IActionResult ResetPwd([FromBody] SysUser sysUser)
|
||||
public IActionResult ResetPwd([FromBody] SysUserDto sysUser)
|
||||
{
|
||||
//密码md5
|
||||
sysUser.Password = NETCore.Encrypt.EncryptProvider.Md5(sysUser.Password);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/userRole")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysUserRoleController : BaseController
|
||||
{
|
||||
private readonly ISysUserRoleService SysUserRoleService;
|
||||
@@ -43,7 +44,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <returns></returns>
|
||||
[HttpPost("create")]
|
||||
[ActionPermissionFilter(Permission = "system:roleusers:add")]
|
||||
[Log(Title = "添加角色用户", BusinessType = Infrastructure.Enums.BusinessType.INSERT)]
|
||||
[Log(Title = "添加角色用户", BusinessType = BusinessType.INSERT)]
|
||||
public IActionResult Create([FromBody] RoleUsersCreateDto roleUsersCreateDto)
|
||||
{
|
||||
var response = SysUserRoleService.InsertRoleUser(roleUsersCreateDto);
|
||||
@@ -58,7 +59,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <returns></returns>
|
||||
[HttpPost("delete")]
|
||||
[ActionPermissionFilter(Permission = "system:roleusers:remove")]
|
||||
[Log(Title = "删除角色用户", BusinessType = Infrastructure.Enums.BusinessType.DELETE)]
|
||||
[Log(Title = "删除角色用户", BusinessType = BusinessType.DELETE)]
|
||||
public IActionResult Delete([FromBody] RoleUsersCreateDto roleUsersCreateDto)
|
||||
{
|
||||
return SUCCESS(SysUserRoleService.DeleteRoleUserByUserIds(roleUsersCreateDto.RoleId, roleUsersCreateDto.UserIds));
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Quartz;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@@ -16,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/Tasks")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class TasksController : BaseController
|
||||
{
|
||||
private ISysTasksQzService _tasksQzService;
|
||||
@@ -87,7 +86,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
throw new CustomException($"程序集或者类名不能为空");
|
||||
}
|
||||
//从 Dto 映射到 实体
|
||||
var tasksQz = parm.Adapt<SysTasks>().ToCreate();
|
||||
var tasksQz = parm.Adapt<SysTasks>().ToCreate(HttpContext);
|
||||
tasksQz.Create_by = HttpContext.GetName();
|
||||
tasksQz.ID = SnowFlakeSingle.Instance.NextId().ToString();
|
||||
|
||||
@@ -159,7 +158,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
var tasksQz = _tasksQzService.GetFirst(m => m.ID == id);
|
||||
var taskResult = await _schedulerServer.DeleteTaskScheduleAsync(tasksQz);
|
||||
|
||||
if (taskResult.Code == 200)
|
||||
if (taskResult.IsSuccess())
|
||||
{
|
||||
_tasksQzService.Delete(id);
|
||||
}
|
||||
@@ -188,7 +187,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
var tasksQz = _tasksQzService.GetFirst(m => m.ID == id);
|
||||
var taskResult = await _schedulerServer.AddTaskScheduleAsync(tasksQz);
|
||||
|
||||
if (taskResult.Code == 200)
|
||||
if (taskResult.IsSuccess())
|
||||
{
|
||||
tasksQz.IsStart = 1;
|
||||
_tasksQzService.Update(tasksQz);
|
||||
@@ -219,7 +218,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
var tasksQz = _tasksQzService.GetFirst(m => m.ID == id);
|
||||
var taskResult = await _schedulerServer.DeleteTaskScheduleAsync(tasksQz);//await _schedulerServer.PauseTaskScheduleAsync(tasksQz);
|
||||
|
||||
if (taskResult.Code == 200)
|
||||
if (taskResult.IsSuccess())
|
||||
{
|
||||
tasksQz.IsStart = 0;
|
||||
_tasksQzService.Update(tasksQz);
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@@ -18,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/monitor/jobLog")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class TasksLogController : BaseController
|
||||
{
|
||||
private readonly ISysTasksLogService tasksLogService;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -14,6 +9,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
/// <summary>
|
||||
/// 系统监控
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class MonitorController : BaseController
|
||||
{
|
||||
private OptionsSetting Options;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
//创建时间:2023-08-17
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据差异日志
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("monitor/SqlDiffLog")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SqlDiffLogController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据差异日志接口
|
||||
/// </summary>
|
||||
private readonly ISqlDiffLogService _SqlDiffLogService;
|
||||
|
||||
public SqlDiffLogController(ISqlDiffLogService SqlDiffLogService)
|
||||
{
|
||||
_SqlDiffLogService = SqlDiffLogService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询数据差异日志列表
|
||||
/// </summary>
|
||||
/// <param name="parm"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("list")]
|
||||
[ActionPermissionFilter(Permission = "sqldifflog:list")]
|
||||
public IActionResult QuerySqlDiffLog([FromQuery] SqlDiffLogQueryDto parm)
|
||||
{
|
||||
var response = _SqlDiffLogService.GetList(parm);
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除数据差异日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{ids}")]
|
||||
[ActionPermissionFilter(Permission = "sqldifflog:delete")]
|
||||
[Log(Title = "数据差异日志", BusinessType = BusinessType.DELETE)]
|
||||
public IActionResult DeleteSqlDiffLog(string ids)
|
||||
{
|
||||
long[] idsArr = Tools.SpitLongArrary(ids);
|
||||
if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); }
|
||||
|
||||
var response = _SqlDiffLogService.Delete(idsArr);
|
||||
|
||||
return ToResponse(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出数据差异日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Log(Title = "数据差异日志", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)]
|
||||
[HttpGet("export")]
|
||||
[ActionPermissionFilter(Permission = "sqldifflog:export")]
|
||||
public IActionResult Export([FromQuery] SqlDiffLogQueryDto parm)
|
||||
{
|
||||
parm.PageNum = 1;
|
||||
parm.PageSize = 100000;
|
||||
var list = _SqlDiffLogService.GetList(parm).Result;
|
||||
if (list == null || list.Count <= 0)
|
||||
{
|
||||
return ToResponse(ResultCode.FAIL, "没有要导出的数据");
|
||||
}
|
||||
var result = ExportExcelMini(list, "数据差异日志", "数据差异日志");
|
||||
return ExportExcel(result.Item2, result.Item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/monitor/logininfor")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysLogininforController : BaseController
|
||||
{
|
||||
private ISysLoginService sysLoginService;
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/monitor/operlog")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysOperlogController : BaseController
|
||||
{
|
||||
private ISysOperLogService sysOperLogService;
|
||||
@@ -65,7 +66,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
{
|
||||
if (!HttpContextExtension.IsAdmin(HttpContext))
|
||||
{
|
||||
return ToResponse(Infrastructure.ResultCode.CUSTOM_ERROR,"操作失败");
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR,"操作失败");
|
||||
}
|
||||
sysOperLogService.CleanOperLog();
|
||||
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Admin.WebApi.Hubs;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.ServiceCore.Signalr;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
{
|
||||
/// <summary>
|
||||
/// 在线用户
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("monitor/online")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysUserOnlineController : BaseController
|
||||
{
|
||||
private IHubContext<Hub> HubContext;
|
||||
private readonly IHubContext<MessageHub> HubContext;
|
||||
|
||||
public SysUserOnlineController(IHubContext<Hub> hubContext)
|
||||
public SysUserOnlineController(IHubContext<MessageHub> hubContext)
|
||||
{
|
||||
HubContext = hubContext;
|
||||
}
|
||||
@@ -25,11 +30,47 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
[HttpGet("list")]
|
||||
public IActionResult Index([FromQuery] PagerInfo parm)
|
||||
{
|
||||
var result = MessageHub.clientUsers
|
||||
var result = MessageHub.onlineClients
|
||||
.OrderByDescending(f => f.LoginTime)
|
||||
.Skip(parm.PageNum - 1).Take(parm.PageSize);
|
||||
|
||||
return SUCCESS(new { result, totalNum = MessageHub.clientUsers.Count });
|
||||
return SUCCESS(new { result, totalNum = MessageHub.onlineClients.Count });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单个强退
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("force")]
|
||||
[Log(Title = "强退", BusinessType = BusinessType.FORCE)]
|
||||
[ActionPermissionFilter(Permission = "monitor:online:forceLogout")]
|
||||
public async Task<IActionResult> Force([FromBody] LockUserDto dto)
|
||||
{
|
||||
if (dto == null) { return ToResponse(ResultCode.PARAM_ERROR); }
|
||||
|
||||
await HubContext.Clients.Client(dto.ConnnectionId)
|
||||
.SendAsync(HubsConstant.ForceUser, new { dto.Reason, dto.Time });
|
||||
|
||||
//var expirTime = DateTimeHelper.GetUnixTimeSeconds(DateTime.Now.AddMinutes(dto.Time));
|
||||
////PC 端采用设备 + 用户名的方式进行封锁
|
||||
//CacheService.SetLockUser(dto.ClientId + dto.Name, expirTime, dto.Time);
|
||||
return SUCCESS(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量强退
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("batchForce")]
|
||||
[Log(Title = "强退", BusinessType = BusinessType.FORCE)]
|
||||
[ActionPermissionFilter(Permission = "monitor:online:batchLogout")]
|
||||
public async Task<IActionResult> BatchforceLogout([FromBody] LockUserDto dto)
|
||||
{
|
||||
if (dto == null) { return ToResponse(ResultCode.PARAM_ERROR); }
|
||||
|
||||
await HubContext.Clients.All.SendAsync(HubsConstant.ForceUser, new { dto.Reason });
|
||||
|
||||
return SUCCESS(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Web;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
@@ -11,9 +10,6 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
[AllowAnonymous]
|
||||
public class WxOpenController : BaseController
|
||||
{
|
||||
private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
public WxOpenController() { }
|
||||
|
||||
/// <summary>
|
||||
/// 获取签名
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Infrastructure;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.Filters;
|
||||
using Swashbuckle.AspNetCore.SwaggerUI;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
@@ -33,7 +33,13 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
};
|
||||
});
|
||||
});
|
||||
app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "ZrAdmin v1"));
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("sys/swagger.json", "系统管理");
|
||||
c.SwaggerEndpoint("article/swagger.json", "文章管理");
|
||||
c.SwaggerEndpoint("v1/swagger.json", "business");
|
||||
c.DocExpansion(DocExpansion.None); //->修改界面打开时自动折叠
|
||||
});
|
||||
}
|
||||
|
||||
public static void AddSwaggerConfig(this IServiceCollection services)
|
||||
@@ -43,6 +49,20 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("sys", new OpenApiInfo
|
||||
{
|
||||
Title = "ZrAdmin.NET Api",
|
||||
Version = "v1",
|
||||
Description = "系统管理",
|
||||
Contact = new OpenApiContact { Name = "ZRAdmin doc", Url = new Uri("https://www.izhaorui.cn/doc") }
|
||||
});
|
||||
c.SwaggerDoc("article", new OpenApiInfo
|
||||
{
|
||||
Title = "ZrAdmin.NET Api",
|
||||
Version = "v1",
|
||||
Description = "文章管理",
|
||||
Contact = new OpenApiContact { Name = "ZRAdmin doc", Url = new Uri("https://www.izhaorui.cn/doc") }
|
||||
});
|
||||
c.SwaggerDoc("v1", new OpenApiInfo
|
||||
{
|
||||
Title = "ZrAdmin.NET Api",
|
||||
@@ -55,6 +75,9 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
//添加文档注释
|
||||
var baseDir = AppContext.BaseDirectory;
|
||||
c.IncludeXmlComments(Path.Combine(baseDir, "ZR.Model.xml"), true);
|
||||
c.IncludeXmlComments(Path.Combine(baseDir, "ZR.ServiceCore.xml"), true);
|
||||
c.IncludeXmlComments(Path.Combine(baseDir, "ZR.Service.xml"), true);
|
||||
c.IncludeXmlComments(Path.Combine(baseDir, "ZR.Admin.WebApi.xml"), true);
|
||||
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
var xmlPath = Path.Combine(baseDir, xmlFile);
|
||||
@@ -94,6 +117,20 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
new List<string>()
|
||||
}
|
||||
});
|
||||
|
||||
//判断接口归于哪个分组
|
||||
c.DocInclusionPredicate((docName, apiDescription) =>
|
||||
{
|
||||
if (docName == "v1")
|
||||
{
|
||||
//当分组为NoGroup时,只要没加特性的都属于这个组
|
||||
return string.IsNullOrEmpty(apiDescription.GroupName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return apiDescription.GroupName == docName;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
foreach (var task in tasks.Result)
|
||||
{
|
||||
var result = _schedulerServer.AddTaskScheduleAsync(task);
|
||||
if (result.Result.Code == 200)
|
||||
if (result.Result.IsSuccess())
|
||||
{
|
||||
Console.WriteLine($"注册任务[{task.Name}]ID:{task.ID}成功");
|
||||
}
|
||||
|
||||
@@ -4,4 +4,7 @@ global using Infrastructure;
|
||||
global using Infrastructure.Attribute;
|
||||
global using Infrastructure.Enums;
|
||||
global using Infrastructure.Model;
|
||||
global using Mapster;
|
||||
global using Mapster;
|
||||
global using Infrastructure.Extensions;
|
||||
global using Infrastructure.Controllers;
|
||||
global using ZR.ServiceCore.Middleware;
|
||||
@@ -1,107 +0,0 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Constant;
|
||||
using Infrastructure.Model;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using UAParser;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Hubs
|
||||
{
|
||||
/// <summary>
|
||||
/// msghub
|
||||
/// </summary>
|
||||
public class MessageHub : Hub
|
||||
{
|
||||
//创建用户集合,用于存储所有链接的用户数据
|
||||
public static readonly List<OnlineUsers> clientUsers = new();
|
||||
private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
private readonly ISysNoticeService SysNoticeService;
|
||||
|
||||
public MessageHub(ISysNoticeService noticeService)
|
||||
{
|
||||
SysNoticeService = noticeService;
|
||||
}
|
||||
|
||||
private ApiResult SendNotice()
|
||||
{
|
||||
var result = SysNoticeService.GetSysNotices();
|
||||
|
||||
return new ApiResult(200, "success", result);
|
||||
}
|
||||
|
||||
#region 客户端连接
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接的时候调用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override Task OnConnectedAsync()
|
||||
{
|
||||
var name = HttpContextExtension.GetName(App.HttpContext);
|
||||
var ip = HttpContextExtension.GetClientUserIp(App.HttpContext);
|
||||
var ip_info = IpTool.Search(ip);
|
||||
|
||||
ClientInfo clientInfo = HttpContextExtension.GetClientInfo(App.HttpContext);
|
||||
string device = clientInfo.ToString();
|
||||
|
||||
var userid = HttpContextExtension.GetUId(App.HttpContext);
|
||||
string uuid = device + userid + ip;
|
||||
var user = clientUsers.Any(u => u.ConnnectionId == Context.ConnectionId);
|
||||
var user2 = clientUsers.Any(u => u.Uuid == uuid);
|
||||
|
||||
//判断用户是否存在,否则添加集合!user2 && !user &&
|
||||
if (!user2 && !user && Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
OnlineUsers users = new(Context.ConnectionId, name, userid, ip, device)
|
||||
{
|
||||
Location = ip_info.City,
|
||||
Uuid = uuid
|
||||
};
|
||||
clientUsers.Add(users);
|
||||
Console.WriteLine($"{DateTime.Now}:{name},{Context.ConnectionId}连接服务端success,当前已连接{clientUsers.Count}个");
|
||||
//Clients.All.SendAsync("welcome", $"欢迎您:{name},当前时间:{DateTime.Now}");
|
||||
Clients.All.SendAsync(HubsConstant.MoreNotice, SendNotice());
|
||||
}
|
||||
|
||||
Clients.All.SendAsync(HubsConstant.OnlineNum, clientUsers.Count);
|
||||
return base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接终止时调用。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
var user = clientUsers.Where(p => p.ConnnectionId == Context.ConnectionId).FirstOrDefault();
|
||||
//判断用户是否存在,否则添加集合
|
||||
if (user != null)
|
||||
{
|
||||
clientUsers.Remove(user);
|
||||
Clients.All.SendAsync(HubsConstant.OnlineNum, clientUsers.Count);
|
||||
|
||||
Console.WriteLine($"用户{user?.Name}离开了,当前已连接{clientUsers.Count}个");
|
||||
}
|
||||
return base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 注册信息
|
||||
/// </summary>
|
||||
/// <param name="connectId"></param>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
[HubMethodName("SendMessage")]
|
||||
public async Task SendMessage(string connectId, string userName, string message)
|
||||
{
|
||||
Console.WriteLine($"{connectId},message={message}");
|
||||
|
||||
await Clients.Client(connectId).SendAsync("receiveChat", new { userName, message });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
namespace ZR.Admin.WebApi.Hubs
|
||||
{
|
||||
public class OnlineUsers
|
||||
{
|
||||
/// <summary>
|
||||
/// 客户端连接Id
|
||||
/// </summary>
|
||||
public string ConnnectionId { get; set; }
|
||||
/// <summary>
|
||||
/// 用户id
|
||||
/// </summary>
|
||||
public long? Userid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public DateTime LoginTime { get; set; }
|
||||
public string UserIP { get; set; }
|
||||
/// <summary>
|
||||
/// 登录地点
|
||||
/// </summary>
|
||||
public string? Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判断用户唯一
|
||||
/// </summary>
|
||||
public string? Uuid{ get; set; }
|
||||
/// <summary>
|
||||
/// 浏览器
|
||||
/// </summary>
|
||||
public string Browser { get; set; }
|
||||
|
||||
public OnlineUsers(string clientid, string name, long? userid, string userip, string browser)
|
||||
{
|
||||
ConnnectionId = clientid;
|
||||
Name = name;
|
||||
LoginTime = DateTime.Now;
|
||||
Userid = userid;
|
||||
UserIP = userip;
|
||||
Browser = browser;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-15
@@ -24,29 +24,29 @@
|
||||
<!--${basedir}表示当前应用程序域所在的根目录-->
|
||||
<target name="allfile" xsi:type="File"
|
||||
fileName="${basedir}/adminlogs/all.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/all.{###}.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/all/all.{###}.txt"
|
||||
archiveEvery="Day"
|
||||
archiveNumbering="DateAndSequence"
|
||||
archiveAboveSize="20000000"
|
||||
maxArchiveFiles="30"
|
||||
keepFileOpen="true"
|
||||
layout="${longdate} | ${event-properties:item=EventId_Id} | ${uppercase:${level}} | ${logger} | ${aspnet-request-iP:CheckForwardedForHeader=true} | ${event-properties:item=user} | ${aspnet-request-url} | ${message} | ${event-properties:item=requestParam} | ${event-properties:item=jsonResult} | ${onexception:${exception:format=tostring}"/>
|
||||
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${aspnet-request-connection-id}|${uppercase:${level}}|${logger}|${aspnet-request-iP:CheckForwardedForHeader=true}|${event-properties:item=user:whenEmpty=-}|url: ${aspnet-request-url}|${message:whenEmpty=-}|${event-properties:item=requestParam}|${event-properties:item=jsonResult}"/>
|
||||
|
||||
<!--错误日志-->
|
||||
<target name="errorfile" xsi:type="File"
|
||||
fileName="${basedir}/adminlogs/error.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/error.{###}.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/error/error.{###}.txt"
|
||||
archiveEvery="Day"
|
||||
archiveNumbering="DateAndSequence"
|
||||
archiveAboveSize="20000000"
|
||||
maxArchiveFiles="30"
|
||||
keepFileOpen="true"
|
||||
layout="${longdate} | ${event-properties:item=EventId_Id} | ${uppercase:${level}} | ${logger} | ${aspnet-request-iP:CheckForwardedForHeader=true} | ${event-properties:item=user} | ${aspnet-request-url} | ${message} | ${event-properties:item=requestParam} | ${event-properties:item=jsonResult} | ${onexception:${exception:format=tostring}"/>
|
||||
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${uppercase:${level}}|${logger}${newline}用户IP:${aspnet-request-iP:CheckForwardedForHeader=true}|${event-properties:item=user}${newline}请求地址:${aspnet-request-url}${newline}错误消息:${message}${newline}请求参数:${event-properties:item=requestParam}${newline}请求结果:${event-properties:item=jsonResult}${newline}${onexception:${exception:format=tostring}"/>
|
||||
|
||||
<!--SQL文件-->
|
||||
<target name="sqlfile" xsi:type="File"
|
||||
fileName="${basedir}/adminlogs/admin-sql.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/admin-sql{###}.txt"
|
||||
fileName="${basedir}/adminlogs/sql.txt"
|
||||
archiveFileName="${basedir}/adminlogs/bak/sql/sql{###}.txt"
|
||||
archiveEvery="Day"
|
||||
archiveNumbering="DateAndSequence"
|
||||
archiveAboveSize="20000000"
|
||||
@@ -56,18 +56,17 @@
|
||||
|
||||
<!--写入彩色控制台-->
|
||||
<target name="consoleSql" xsi:type="ColoredConsole" useDefaultRowHighlightingRules="false"
|
||||
layout="${date:format=MM-dd HH\:mm\:ss} | ${aspnet-request-iP} | ${aspnet-request-url} ${newline}${message}">
|
||||
layout="${date:format=MM-dd HH\:mm\:ss}|${aspnet-request-iP}|${aspnet-request-url}${newline}${message}">
|
||||
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
|
||||
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
|
||||
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
|
||||
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
|
||||
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
|
||||
<highlight-word regex="SQL语句" foregroundColor="Blue" />
|
||||
<highlight-word regex="SQL" foregroundColor="Blue" />
|
||||
<highlight-word regex="【" foregroundColor="Blue" />
|
||||
<highlight-word regex="】" foregroundColor="Blue" />
|
||||
</target>
|
||||
|
||||
<target name="console" xsi:type="ColoredConsole"
|
||||
layout="${date:format=MM-dd HH\:mm\:ss} | ${aspnet-request-url} ${newline} ${message}"/>
|
||||
|
||||
<!--写入黑洞-->
|
||||
<target name="blackhole" xsi:type="Null" />
|
||||
</targets>
|
||||
@@ -80,11 +79,10 @@
|
||||
<!--<logger name="System.*" writeTo="blackhole" final="true" />-->
|
||||
<!-- Quartz -->
|
||||
<logger name="Quartz*" minlevel="Trace" maxlevel="Info" final="true" />
|
||||
<logger name="ZR.Admin.WebApi.Middleware.GlobalExceptionMiddleware" final="true" writeTo="console,errorfile"/>
|
||||
<logger name="ZR.Admin.WebApi.Extensions.DbExtension" final="true" writeTo="consoleSql,sqlfile"/>
|
||||
<logger name="*" writeTo="console"/>
|
||||
|
||||
<logger name="*.SqlSugar.SqlsugarSetup" final="true" writeTo="consoleSql,sqlfile"/>
|
||||
<logger name="*" minLevel="Trace" writeTo="allfile" />
|
||||
<logger name="*.GlobalExceptionMiddleware" final="true" writeTo="consoleSql,errorfile"/>
|
||||
|
||||
<!--Skip non-critical Microsoft logs and so log only own logs-->
|
||||
<logger name="Microsoft.*,Quartz.Core.QuartzSchedulerThread" maxlevel="Info" final="true" />
|
||||
</rules>
|
||||
|
||||
+31
-36
@@ -1,17 +1,19 @@
|
||||
using AspNetCoreRateLimit;
|
||||
using Infrastructure;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Infrastructure.Converter;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NLog.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Admin.WebApi.Framework;
|
||||
using ZR.Admin.WebApi.Hubs;
|
||||
using ZR.Admin.WebApi.Middleware;
|
||||
using ZR.Common.Cache;
|
||||
using ZR.Infrastructure.WebExtensions;
|
||||
using ZR.ServiceCore.Signalr;
|
||||
using ZR.ServiceCore.SqlSugar;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
// NLog: Setup NLog for Dependency injection
|
||||
//builder.Logging.ClearProviders();
|
||||
builder.Host.UseNLog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers();
|
||||
@@ -24,8 +26,6 @@ builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
builder.Services.AddCors(builder.Configuration);
|
||||
// 显示logo
|
||||
builder.Services.AddLogo();
|
||||
//注入SignalR实时通讯,默认用json传输
|
||||
builder.Services.AddSignalR();
|
||||
//消除Error unprotecting the session cookie警告
|
||||
builder.Services.AddDataProtection()
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
|
||||
@@ -39,30 +39,10 @@ builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.Configure<OptionsSetting>(builder.Configuration);
|
||||
|
||||
//jwt 认证
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
}).AddCookie()
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
o.TokenValidationParameters = JwtUtil.ValidParameters();
|
||||
o.Events = new JwtBearerEvents
|
||||
{
|
||||
OnAuthenticationFailed = context =>
|
||||
{
|
||||
// 如果过期,把过期信息添加到头部
|
||||
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
|
||||
{
|
||||
context.Response.Headers.Add("Token-Expired", "true");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddJwt();
|
||||
//配置文件
|
||||
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
|
||||
//app服务注册
|
||||
builder.Services.AddAppService();
|
||||
//开启计划任务
|
||||
builder.Services.AddTaskSchedulers();
|
||||
@@ -80,12 +60,21 @@ builder.Services.AddMvc(options =>
|
||||
})
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString;
|
||||
//options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString;
|
||||
options.JsonSerializerOptions.WriteIndented = true;
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeConverter());
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeNullConverter());
|
||||
options.JsonSerializerOptions.Converters.Add(new StringConverter());
|
||||
//PropertyNamingPolicy属性用于前端传过来的属性的格式策略,目前内置的仅有一种策略CamelCase
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
//options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;//属性可以忽略大小写格式,开启后性能会降低
|
||||
});
|
||||
//注入SignalR实时通讯,默认用json传输
|
||||
builder.Services.AddSignalR()
|
||||
.AddJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
});
|
||||
|
||||
builder.Services.AddSwaggerConfig();
|
||||
|
||||
var app = builder.Build();
|
||||
@@ -93,11 +82,18 @@ InternalApp.ServiceProvider = app.Services;
|
||||
InternalApp.Configuration = builder.Configuration;
|
||||
InternalApp.WebHostEnvironment = app.Environment;
|
||||
//初始化db
|
||||
builder.Services.AddDb(builder.Configuration, app.Environment);
|
||||
builder.Services.AddDb(app.Environment);
|
||||
|
||||
//使用全局异常中间件
|
||||
app.UseMiddleware<GlobalExceptionMiddleware>();
|
||||
|
||||
//请求头转发
|
||||
//ForwardedHeaders中间件会自动把反向代理服务器转发过来的X-Forwarded-For(客户端真实IP)以及X-Forwarded-Proto(客户端请求的协议)自动填充到HttpContext.Connection.RemoteIPAddress和HttpContext.Request.Scheme中,这样应用代码中读取到的就是真实的IP和真实的协议了,不需要应用做特殊处理。
|
||||
app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
{
|
||||
ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
|
||||
});
|
||||
|
||||
app.Use((context, next) =>
|
||||
{
|
||||
//设置可以多次获取body内容
|
||||
@@ -138,5 +134,4 @@ app.MapControllerRoute(
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
@@ -6,7 +6,7 @@
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>1701;1702;1591,8603,8602,8604,8600</NoWarn>
|
||||
<NoWarn>1701;1702;1591,8603,8602,8604,8600,8618</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -15,17 +15,12 @@
|
||||
<ProjectReference Include="..\ZR.Tasks\ZR.Tasks.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Lazy.Captcha.Core" Version="2.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.7" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
<PackageReference Include="NLog" Version="5.2.0" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.3" />
|
||||
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.3" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -36,5 +31,11 @@
|
||||
<None Update="ip2region.db">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Update="wwwroot\Generatecode\**\*">
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\export\**\*">
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"Conn": "Data Source=LAPTOP-STKF2M8H\\SQLEXPRESS;User ID=admin;Password=admin123;Initial Catalog={dbName};",
|
||||
"DbType": 1,
|
||||
"IsAutoCloseConnection": true,
|
||||
"DbName": "ZrAdmin" //代码生成默认连接数据库
|
||||
"DbName": "ZrAdmin" //代码生成默认连接数据库,Oracle库是实例的名称
|
||||
},
|
||||
"urls": "http://localhost:8888", //项目启动url,如果改动端口前端对应devServer也需要进行修改
|
||||
"corsUrls": [ "http://localhost:8887", "http://localhost:8886" ], //跨域地址(前端启动项目,前后端分离单独部署需要设置),多个用","隔开
|
||||
@@ -29,11 +29,15 @@
|
||||
"Issuer": "ZRAdmin.NET", //即token的签发者。
|
||||
"Audience": "ZRAdmin.NET", //指该token是服务于哪个群体的(群体范围)
|
||||
"SecretKey": "SecretKey-ZRADMIN.NET-20210101",
|
||||
"Expire": 1440 //jwt登录过期时间(分)
|
||||
"Expire": 1440, //jwt登录过期时间(分)
|
||||
"RefreshTokenTime": 5,//分钟
|
||||
"TokenType": "Bearer"
|
||||
},
|
||||
"InjectClass": [ "ZR.Repository", "ZR.Service", "ZR.Tasks" ], //自动注入类
|
||||
"InjectClass": [ "ZR.Repository", "ZR.Service", "ZR.Tasks", "ZR.ServiceCore" ], //自动注入类
|
||||
"ShowDbLog": true, //是否打印db日志
|
||||
"InitDb": false, //是否初始化db
|
||||
"DemoMode": false, //是否演示模式
|
||||
"SingleLogin": false,//是否单点登录
|
||||
"Upload": {
|
||||
"uploadUrl": "http://localhost:8888", //本地存储资源访问路径
|
||||
"localSavePath": "", //本地上传默认文件存储目录 wwwroot
|
||||
@@ -108,7 +112,7 @@
|
||||
"RealIpHeader": "X-Real-IP",
|
||||
"ClientIdHeader": "X-ClientId",
|
||||
"HttpStatusCode": 429,
|
||||
"EndpointWhitelist": [ "post:/system/dict/data/types", "*:/msghub/negotiate", "*:/LogOut", "*:/common/uploadfile" ],
|
||||
"EndpointWhitelist": [ "post:/system/dict/data/types", "*:/msghub/negotiate", "*:/LogOut", "*:/common/uploadfile", "*:/VerifyScan" ],
|
||||
"QuotaExceededResponse": {
|
||||
"Content": "{{\"code\":429,\"msg\":\"访问过于频繁,请稍后重试\"}}",
|
||||
"ContentType": "application/json",
|
||||
@@ -127,12 +131,7 @@
|
||||
"Period": "3s",
|
||||
"Limit": 1
|
||||
}
|
||||
],
|
||||
"IpRateLimitPolicies": {
|
||||
//ip规则
|
||||
"IpRules": [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
//验证码配置
|
||||
"CaptchaOptions": {
|
||||
|
||||
@@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using ${options.DtosNamespace};
|
||||
using ${options.ModelsNamespace}.${options.SubNamespace};
|
||||
using ${options.IServicsNamespace}.${options.SubNamespace}.I${options.SubNamespace}Service;
|
||||
using ${options.ApiControllerNamespace}.Extensions;
|
||||
using ${options.ApiControllerNamespace}.Filters;
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
using MiniExcelLibs;
|
||||
|
||||
@@ -117,7 +117,7 @@ $end
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName)
|
||||
return Context.InsertNav(model).Include(s1 => s1.${genTable.SubTable.ClassName}Nav).ExecuteReturnEntity();
|
||||
$else
|
||||
return Insertable(model).IgnoreColumns(true).ExecuteReturnEntity();
|
||||
return Context.Insertable(model).ExecuteReturnEntity();
|
||||
$end
|
||||
}
|
||||
|
||||
|
||||
@@ -69,12 +69,14 @@ $end
|
||||
|
||||
</u--form>
|
||||
|
||||
<view class="btn-group">
|
||||
<view class="btn-item">
|
||||
<u-button text="取消" shape="circle" icon="close" type="info" @click="handleCancel"></u-button>
|
||||
</view>
|
||||
<view class="btn-item" v-if="opertype != 3">
|
||||
<u-button text="确定" shape="circle" icon="checkmark" type="primary" @click="submit"></u-button>
|
||||
<view class="form-footer">
|
||||
<view class="btn_wrap">
|
||||
<view class="btn-item">
|
||||
<u-button text="取消" shape="circle" type="info" @click="handleCancel"></u-button>
|
||||
</view>
|
||||
<view class="btn-item" v-if="opertype != 3">
|
||||
<u-button text="确定" shape="circle" type="primary" @click="submit"></u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -110,7 +112,6 @@ $end
|
||||
return {
|
||||
form: {},
|
||||
rules: {
|
||||
xxx: {},
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.IsRequired && column.IsIncrement == false)
|
||||
${column.CsharpFieldFl}: [{
|
||||
@@ -185,12 +186,10 @@ $end
|
||||
update${genTable.BusinessName}(this.form).then((res) => {
|
||||
this.${modal}modal.msgSuccess("修改成功")
|
||||
})
|
||||
.catch(() => {})
|
||||
} else {
|
||||
add${genTable.BusinessName}(this.form).then((res) => {
|
||||
this.${modal}modal.msgSuccess("新增成功")
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
}).catch(errors => {
|
||||
this.${modal}modal.msg('表单校验失败')
|
||||
|
||||
@@ -197,7 +197,7 @@ $elseif(tool.CheckTree(genTable ,column.CsharpField))
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.IsPK || column.IsIncrement)
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
$if(column.IsIncrement == false)
|
||||
<el-input-number v-model.number="form.${columnName}" controls-position="right" placeholder="请输入${labelName}" :disabled="title=='修改数据'"/>
|
||||
@@ -208,13 +208,13 @@ $end
|
||||
</el-col>
|
||||
$else
|
||||
$if(column.HtmlType == "inputNumber")
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-input-number v-model.number="form.${columnName}" controls-position="right" placeholder="请输入${labelName}" ${labelDisabled}/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "datetime")
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-date-picker v-model="form.${columnName}" type="datetime" placeholder="选择日期时间"></el-date-picker>
|
||||
</el-form-item>
|
||||
@@ -232,7 +232,7 @@ $elseif(column.HtmlType == "fileUpload")
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "radio")
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-radio-group v-model="form.${columnName}">
|
||||
<el-radio v-for="item in $if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :key="item.dictValue" :label="${value}">{{item.dictLabel}}</el-radio>
|
||||
@@ -252,7 +252,7 @@ $elseif(column.HtmlType == "editor")
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "select" || column.HtmlType == "selectMulti")
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-select v-model="form.${columnName}" placeholder="请选择${labelName}"${column.DisabledStr}>
|
||||
<el-option v-for="item in $if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :key="item.dictValue" :label="item.dictLabel" :value="${value}"></el-option>
|
||||
@@ -268,7 +268,7 @@ $elseif(column.HtmlType == "checkbox")
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$else
|
||||
<el-col :lg="12">
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-input v-model="form.${columnName}" placeholder="请输入${labelName}" ${labelDisabled}/>
|
||||
</el-form-item>
|
||||
@@ -301,10 +301,8 @@ import Editor from '@/components/Editor'
|
||||
$end
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
// 是否展开,默认全部折叠
|
||||
const isExpandAll = ref(false)
|
||||
const refreshTable = ref(true)
|
||||
// 展开/折叠操作
|
||||
function toggleExpandAll() {
|
||||
refreshTable.value = false
|
||||
isExpandAll.value = !isExpandAll.value
|
||||
|
||||
@@ -53,7 +53,7 @@ $elseif(column.HtmlType == "datePicker")
|
||||
:default-time="defaultTime">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
$elseif(column.HtmlType.Contains("select") || column.HtmlType == "radio")
|
||||
$elseif(column.HtmlType.Contains("select"))
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-select clearable $if(column.HtmlType == "selectMulti")multiple$end v-model="queryParams.${columnName}" placeholder="请选择${labelName}">
|
||||
<el-option v-for="item in $if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue">
|
||||
@@ -65,6 +65,7 @@ $elseif(column.HtmlType.Contains("select") || column.HtmlType == "radio")
|
||||
$elseif(column.HtmlType == "radio")
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-radio-group v-model="queryParams.${columnName}">
|
||||
<el-radio>全部</el-radio>
|
||||
<el-radio v-for="item in $if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :key="item.dictValue" :label="item.dictValue">{{item.dictLabel}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -81,7 +82,7 @@ $end
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 工具区域 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-row :gutter="15" class="mb10">
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" v-hasPermi="['${replaceDto.PermissionPrefix}:add']" plain icon="plus" @click="handleAdd">
|
||||
@@ -187,7 +188,7 @@ $elseif(column.HtmlType == "imageUpload")
|
||||
$elseif(column.HtmlType == "checkbox" || column.HtmlType.Contains("select") || column.HtmlType == "radio")
|
||||
<el-table-column prop="${columnName}" label="${labelName}" align="center"${column.sortStr} v-if="columns.showColumn('${columnName}')">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="$if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :value="scope.row.${columnName}" $if(column.HtmlType == "checkbox")split=","$end />
|
||||
<dict-tag :options="$if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :value="scope.row.${columnName}" $if(column.HtmlType == "checkbox" || column.HtmlType == "selectMulti")split=","$end />
|
||||
</template>
|
||||
</el-table-column>
|
||||
$elseif(column.HtmlType == "datetime")
|
||||
@@ -213,13 +214,13 @@ $end
|
||||
</el-button-group>
|
||||
$else
|
||||
$if(replaceDto.ShowBtnView)
|
||||
<el-button type="primary" icon="view" title="详情" @click="handlePreview(scope.row)"></el-button>
|
||||
<el-button type="primary" size="small" icon="view" title="详情" @click="handlePreview(scope.row)"></el-button>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
<el-button v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" type="success" icon="edit" title="编辑" @click="handleUpdate(scope.row)"></el-button>
|
||||
<el-button type="success" size="small" icon="edit" title="编辑" v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" @click="handleUpdate(scope.row)"></el-button>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnDelete)
|
||||
<el-button v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" type="danger" icon="delete" title="删除" @click="handleDelete(scope.row)"></el-button>
|
||||
<el-button type="danger" size="small" icon="delete" title="删除" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" @click="handleDelete(scope.row)"></el-button>
|
||||
$end
|
||||
$end
|
||||
</template>
|
||||
@@ -326,10 +327,16 @@ $elseif(column.HtmlType == "editor")
|
||||
<editor v-model="form.${columnName}" :min-height="200" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "slider")
|
||||
<el-col :lg="24">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-slider v-model="form.${columnName}" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "select" || column.HtmlType == "selectMulti")
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-select v-model="form.${columnName}" placeholder="请选择${labelName}"${column.DisabledStr}>
|
||||
<el-select v-model="form.${columnName}$if(column.HtmlType == "selectMulti")Checked$end" $if(column.HtmlType == "selectMulti")multiple$end placeholder="请选择${labelName}"${column.DisabledStr}>
|
||||
<el-option
|
||||
v-for="item in $if(column.DictType != "")options.${column.DictType}${else}options.${column.CsharpFieldFl}Options$end"
|
||||
:key="item.dictValue"
|
||||
@@ -442,7 +449,9 @@ $end
|
||||
</el-form>
|
||||
<template #footer v-if="opertype != 3">
|
||||
<el-button text @click="cancel">{{ ${t}t('btn.cancel') }}</el-button>
|
||||
$if(replaceDto.ShowBtnEdit || replaceDto.ShowBtnAdd)
|
||||
<el-button type="primary" @click="submitForm">{{ ${t}t('btn.submit') }}</el-button>
|
||||
$end
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -654,7 +663,7 @@ function cancel(){
|
||||
function reset() {
|
||||
form.value = {
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "checkbox"))
|
||||
$if(item.HtmlType == "checkbox" || item.HtmlType == "selectMulti")
|
||||
${item.CsharpFieldFl}Checked: [],
|
||||
$else
|
||||
$item.CsharpFieldFl: null,
|
||||
@@ -666,7 +675,7 @@ $if(sub)
|
||||
$end
|
||||
proxy.resetForm("formRef")
|
||||
}
|
||||
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
// 添加按钮操作
|
||||
function handleAdd() {
|
||||
reset();
|
||||
@@ -674,7 +683,8 @@ function handleAdd() {
|
||||
title.value = '添加${genTable.functionName}'
|
||||
opertype.value = 1
|
||||
}
|
||||
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
// 修改按钮操作
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
@@ -689,7 +699,7 @@ function handleUpdate(row) {
|
||||
form.value = {
|
||||
...data,
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.HtmlType == "checkbox")
|
||||
$if(item.HtmlType == "checkbox" || item.HtmlType == "selectMulti")
|
||||
${item.CsharpFieldFl}Checked: data.${item.CsharpFieldFl} ? data.${item.CsharpFieldFl}.split(',') : [],
|
||||
$end
|
||||
$end
|
||||
@@ -700,13 +710,14 @@ $end
|
||||
}
|
||||
})
|
||||
}
|
||||
$end
|
||||
|
||||
// 添加&修改 表单提交
|
||||
function submitForm() {
|
||||
proxy.${refs}refs["formRef"].validate((valid) => {
|
||||
if (valid) {
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.HtmlType == "checkbox")
|
||||
$if(item.HtmlType == "checkbox" || item.HtmlType == "selectMulti")
|
||||
form.value.${item.CsharpFieldFl} = form.value.${item.CsharpFieldFl}Checked.toString();
|
||||
$end
|
||||
$end
|
||||
@@ -715,24 +726,27 @@ $if(sub)
|
||||
form.value.${tool.FirstLowerCase(genTable.SubTable.ClassName)}Nav = ${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value
|
||||
$end
|
||||
if (form.value.${replaceDto.FistLowerPk} != undefined && opertype.value === 2) {
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
update${genTable.BusinessName}(form.value).then((res) => {
|
||||
proxy.${modal}modal.msgSuccess("修改成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
.catch(() => {})
|
||||
$end
|
||||
} else {
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
add${genTable.BusinessName}(form.value).then((res) => {
|
||||
proxy.${modal}modal.msgSuccess("新增成功")
|
||||
open.value = false
|
||||
getList()
|
||||
})
|
||||
.catch(() => {})
|
||||
$end
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$if(replaceDto.ShowBtnMultiDel || replaceDto.ShowBtnDelete)
|
||||
// 删除按钮操作
|
||||
function handleDelete(row) {
|
||||
const Ids = row.${replaceDto.FistLowerPk} || ids.value
|
||||
@@ -746,8 +760,8 @@ function handleDelete(row) {
|
||||
getList()
|
||||
proxy.${modal}modal.msgSuccess("删除成功")
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnTruncate)
|
||||
// 清空
|
||||
@@ -778,7 +792,7 @@ function handlePreview(row) {
|
||||
open.value = true
|
||||
title.value = '查看'
|
||||
opertype.value = 3
|
||||
form.value = row
|
||||
form.value = { ...row }
|
||||
}
|
||||
$end
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,5 +1,7 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Helper;
|
||||
using Infrastructure.Model;
|
||||
using JinianNet.JNTemplate;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
@@ -7,7 +9,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ZR.CodeGenerator.Model;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System.Generate;
|
||||
|
||||
namespace ZR.CodeGenerator
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Model;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Model;
|
||||
using SqlSugar;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\ZR.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\ZR.Common\ZR.Common.csproj" />
|
||||
<ProjectReference Include="..\ZR.Model\ZR.Model.csproj" />
|
||||
<ProjectReference Include="..\ZR.ServiceCore\ZR.ServiceCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JinianNet.JNTemplate" Version="2.3.3" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.94" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.105" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
+16
-6
@@ -1,4 +1,5 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Model;
|
||||
using MailKit.Net.Smtp;
|
||||
using MimeKit;
|
||||
using MimeKit.Text;
|
||||
@@ -19,7 +20,7 @@ namespace ZR.Common
|
||||
public MailHelper()
|
||||
{
|
||||
AppSettings.Bind("MailOptions", mailOptions);
|
||||
FromEmail= mailOptions.FromEmail;
|
||||
FromEmail = mailOptions.FromEmail;
|
||||
}
|
||||
public MailHelper(MailOptions _mailOptions)
|
||||
{
|
||||
@@ -132,11 +133,20 @@ namespace ZR.Common
|
||||
//特别说明,对于服务器端的中文相应,Exception中有编码问题,显示乱码了
|
||||
client.Authenticate(System.Text.Encoding.UTF8, mailOptions.FromEmail, mailOptions.Password);
|
||||
|
||||
var result = client.Send(message);
|
||||
//断开
|
||||
client.Disconnect(true);
|
||||
Console.WriteLine($"【{DateTime.Now}】发送邮件结果{result}");
|
||||
return result;
|
||||
try
|
||||
{
|
||||
var result = client.Send(message);
|
||||
//断开
|
||||
client.Disconnect(true);
|
||||
Console.WriteLine($"【{DateTime.Now}】发送邮件结果{result}");
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
client.Disconnect(true);
|
||||
Log.WriteLine(ConsoleColor.Red, "发送邮件失败" + ex.Message);
|
||||
return "fail";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,10 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||
<PackageReference Include="CSRedisCore" Version="3.8.670" />
|
||||
<PackageReference Include="JinianNet.JNTemplate" Version="2.3.3" />
|
||||
<PackageReference Include="MailKit" Version="4.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\ZR.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
此文件夹用于存放业务代码数据库实体类
|
||||
@@ -1,9 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace ZR.Model
|
||||
{
|
||||
public enum ProteryConstant
|
||||
{
|
||||
NOTNULL = 0
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZR.Model.System.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录用户信息存储
|
||||
/// </summary>
|
||||
public class LoginUser
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long DeptId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
/// <summary>
|
||||
/// 角色集合
|
||||
/// </summary>
|
||||
public List<string> RoleIds { get; set; }
|
||||
/// <summary>
|
||||
/// 角色集合(数据权限过滤使用)
|
||||
/// </summary>
|
||||
public List<SysRole> Roles { get; set; }
|
||||
/// <summary>
|
||||
/// 权限集合
|
||||
/// </summary>
|
||||
public List<string> Permissions { get; set; } = new List<string>();
|
||||
public LoginUser()
|
||||
{
|
||||
}
|
||||
|
||||
public LoginUser(SysUser user, List<SysRole> roles, List<string> permissions)
|
||||
{
|
||||
UserId = user.UserId;
|
||||
UserName = user.UserName;
|
||||
DeptId = user.DeptId;
|
||||
Roles = roles;
|
||||
RoleIds = roles.Select(f => f.RoleKey).ToList();
|
||||
Permissions = permissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MiniExcel" Version="1.31.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.94" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.105" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace ZR.Repository
|
||||
|
||||
public int Insert(List<T> t)
|
||||
{
|
||||
return Context.Insertable(t).ExecuteCommand();
|
||||
return InsertRange(t) ? 1 : 0;
|
||||
}
|
||||
public int Insert(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true)
|
||||
{
|
||||
@@ -61,10 +61,10 @@ namespace ZR.Repository
|
||||
#endregion add
|
||||
|
||||
#region update
|
||||
public IUpdateable<T> Updateable(T entity)
|
||||
{
|
||||
return Context.Updateable(entity);
|
||||
}
|
||||
//public IUpdateable<T> Updateable(T entity)
|
||||
//{
|
||||
// return Context.Updateable(entity);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 实体根据主键更新
|
||||
@@ -72,9 +72,10 @@ namespace ZR.Repository
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="ignoreNullColumns"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(T entity, bool ignoreNullColumns = false)
|
||||
public int Update(T entity, bool ignoreNullColumns = false, object data = null)
|
||||
{
|
||||
return Context.Updateable(entity).IgnoreColumns(ignoreNullColumns).ExecuteCommand();
|
||||
return Context.Updateable(entity).IgnoreColumns(ignoreNullColumns)
|
||||
.EnableDiffLogEventIF(data.IsNotEmpty(), data).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,37 +104,6 @@ namespace ZR.Repository
|
||||
return Context.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();
|
||||
}
|
||||
|
||||
public int Update(SqlSugarClient client, T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where)
|
||||
{
|
||||
return client.Updateable(entity).UpdateColumns(expression).Where(where).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="isNull">默认为true</param>
|
||||
/// <returns></returns>
|
||||
public int Update(T entity, List<string> list = null, bool isNull = true)
|
||||
{
|
||||
list ??= new List<string>()
|
||||
{
|
||||
"Create_By",
|
||||
"Create_time"
|
||||
};
|
||||
return Context.Updateable(entity).IgnoreColumns(isNull).IgnoreColumns(list.ToArray()).ExecuteCommand();
|
||||
}
|
||||
|
||||
//public bool Update(List<T> entity)
|
||||
//{
|
||||
// var result = base.Context.Ado.UseTran(() =>
|
||||
// {
|
||||
// base.Context.Updateable(entity).ExecuteCommand();
|
||||
// });
|
||||
// return result.IsSuccess;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 更新指定列 eg:Update(w => w.NoticeId == model.NoticeId, it => new SysNotice(){ Update_time = DateTime.Now, Title = "通知标题" });
|
||||
/// </summary>
|
||||
@@ -160,14 +130,6 @@ namespace ZR.Repository
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public IStorageable<T> Storageable(T t)
|
||||
{
|
||||
return Context.Storageable<T>(t);
|
||||
}
|
||||
public IStorageable<T> Storageable(List<T> t)
|
||||
{
|
||||
return Context.Storageable(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace ZR.Repository
|
||||
#endregion add
|
||||
|
||||
#region update
|
||||
IUpdateable<T> Updateable(T entity);
|
||||
int Update(T entity, bool ignoreNullColumns = false);
|
||||
int Update(T entity, bool ignoreNullColumns = false, object data = null);
|
||||
|
||||
/// <summary>
|
||||
/// 只更新表达式的值
|
||||
@@ -32,13 +31,9 @@ namespace ZR.Repository
|
||||
|
||||
int Update(T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where);
|
||||
|
||||
int Update(SqlSugarClient client, T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where);
|
||||
|
||||
int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns);
|
||||
|
||||
#endregion update
|
||||
IStorageable<T> Storageable(T t);
|
||||
IStorageable<T> Storageable(List<T> t);
|
||||
DbResult<bool> UseTran(Action action);
|
||||
|
||||
DbResult<bool> UseTran(SqlSugarClient client, Action action);
|
||||
|
||||
@@ -5,16 +5,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\ZR.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\ZR.Model\ZR.Model.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.2.6" />
|
||||
<PackageReference Include="NETCore.Encrypt" Version="2.1.1" />
|
||||
<PackageReference Include="SqlSugar.IOC" Version="2.0.0" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.94" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.105" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
global using System.Collections.Generic;
|
||||
global using System.Collections.Generic;
|
||||
global using System;
|
||||
global using SqlSugar;
|
||||
global using Newtonsoft.Json;
|
||||
@@ -0,0 +1,59 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using SqlSugar.IOC;
|
||||
using ZR.Model.System;
|
||||
using ZR.Repository;
|
||||
using ZR.Service.IService;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 注意:下面的AppService不要漏了
|
||||
/// </summary>
|
||||
[AppService(ServiceType = typeof(IHelloService), ServiceLifetime = LifeTime.Transient)]
|
||||
public class HelloService : BaseService<ArticleCategory>, IHelloService
|
||||
{
|
||||
/// <summary>
|
||||
/// 引用User服务
|
||||
/// </summary>
|
||||
private readonly ISysUserService userService;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userService"></param>
|
||||
public HelloService(ISysUserService userService)
|
||||
{
|
||||
this.userService = userService;
|
||||
}
|
||||
/// <summary>
|
||||
/// 数据库使用案例
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public string SayHello(string name)
|
||||
{
|
||||
//构造函数式使用
|
||||
var user = JsonConvert.SerializeObject(userService.GetFirst(f => f.UserId == 1));
|
||||
Console.WriteLine(user);
|
||||
|
||||
var postService = App.GetRequiredService<ISysPostService>();
|
||||
Console.WriteLine(JsonConvert.SerializeObject(postService.GetId(1)));
|
||||
|
||||
BaseRepository<SysDept> deptRepo = new();
|
||||
Console.WriteLine(JsonConvert.SerializeObject(deptRepo.GetId(1)));
|
||||
|
||||
var result = DbScoped.SugarScope.Queryable<SysDictType>().Where(f => f.DictId == 1).First();
|
||||
Console.WriteLine(JsonConvert.SerializeObject(result));
|
||||
|
||||
//切换库
|
||||
//DbScoped.SugarScope.GetConnectionScope(2);
|
||||
|
||||
GetFirst(x => x.CategoryId == 1);
|
||||
Context.Queryable<SysUser>().First(f => f.UserId == 1);
|
||||
|
||||
return "Hello:" + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using ZR.Model.System;
|
||||
|
||||
namespace ZR.Service.IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Hello接口
|
||||
/// </summary>
|
||||
public interface IHelloService : IBaseService<ArticleCategory>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
string SayHello(string name);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZR.Common;
|
||||
using ZR.Common.Cache;
|
||||
|
||||
namespace ZR.Service.System
|
||||
{
|
||||
public class CacheService
|
||||
{
|
||||
#region 用户权限 缓存
|
||||
public static List<string> GetUserPerms(string key)
|
||||
{
|
||||
return (List<string>)CacheHelper.GetCache(key);
|
||||
//return RedisServer.Cache.Get<List<string>>(key).ToList();
|
||||
}
|
||||
|
||||
public static void SetUserPerms(string key, object data)
|
||||
{
|
||||
CacheHelper.SetCache(key, data);
|
||||
//RedisServer.Cache.Set(key, data);
|
||||
}
|
||||
public static void RemoveUserPerms(string key)
|
||||
{
|
||||
CacheHelper.Remove(key);
|
||||
//RedisServer.Cache.Del(key);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ZR.Common\ZR.Common.csproj" />
|
||||
<ProjectReference Include="..\ZR.Repository\ZR.Repository.csproj" />
|
||||
<ProjectReference Include="..\ZR.ServiceCore\ZR.ServiceCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -8,11 +8,5 @@ namespace ZR.Service
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class BaseService<T> : BaseRepository<T> where T : class, new()
|
||||
{
|
||||
//public IBaseRepository<T> baseRepository;
|
||||
|
||||
//public BaseService(IBaseRepository<T> repository)
|
||||
//{
|
||||
// this.baseRepository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||
//}
|
||||
}
|
||||
}
|
||||
+28
-15
@@ -2,9 +2,11 @@
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Filters
|
||||
namespace ZR.ServiceCore.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// API授权判断
|
||||
@@ -17,8 +19,11 @@ namespace ZR.Admin.WebApi.Filters
|
||||
/// 权限字符串,例如 system:user:view
|
||||
/// </summary>
|
||||
public string Permission { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// 角色字符串,例如 common,admin
|
||||
/// </summary>
|
||||
public string RolePermi { get; set; } = string.Empty;
|
||||
private bool HasPermi { get; set; }
|
||||
private bool HasRole { get; set; }
|
||||
public ActionPermissionFilter() { }
|
||||
public ActionPermissionFilter(string permission)
|
||||
{
|
||||
@@ -34,12 +39,22 @@ namespace ZR.Admin.WebApi.Filters
|
||||
/// <returns></returns>
|
||||
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
LoginUser info = Framework.JwtUtil.GetLoginUser(context.HttpContext);
|
||||
TokenModel info = JwtUtil.GetLoginUser(context.HttpContext);
|
||||
|
||||
if (info != null && info?.UserId > 0)
|
||||
{
|
||||
List<string> perms = info.Permissions;
|
||||
long userId = info.UserId;
|
||||
List<string> perms = CacheService.GetUserPerms(GlobalConstant.UserPermKEY + userId);
|
||||
List<string> rolePerms = info.RoleIds;
|
||||
|
||||
if (perms == null)
|
||||
{
|
||||
var sysPermissionService = App.GetService<ISysPermissionService>();
|
||||
perms = sysPermissionService.GetMenuPermission(new SysUser() { UserId = userId });
|
||||
|
||||
CacheService.SetUserPerms(GlobalConstant.UserPermKEY + userId, perms);
|
||||
}
|
||||
|
||||
if (perms.Exists(f => f.Equals(GlobalConstant.AdminPerm)))
|
||||
{
|
||||
HasPermi = true;
|
||||
@@ -52,24 +67,22 @@ namespace ZR.Admin.WebApi.Filters
|
||||
{
|
||||
HasPermi = perms.Exists(f => f.ToLower() == Permission.ToLower());
|
||||
}
|
||||
|
||||
if (!HasPermi && !string.IsNullOrEmpty(RolePermi))
|
||||
{
|
||||
HasPermi = info.RoleIds.Contains(RolePermi);
|
||||
}
|
||||
bool isDemoMode = AppSettings.GetAppConfig("DemoMode", false);
|
||||
var url = context.HttpContext.Request.Path;
|
||||
//演示公开环境屏蔽权限
|
||||
string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "send", "export", "upload", "common", "gencode", "reset" };
|
||||
if (isDemoMode && denyPerms.Any(f => Permission.ToLower().Contains(f)))
|
||||
string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "send", "export", "upload", "common", "gencode", "reset", "forceLogout", "batchLogout" };
|
||||
if (isDemoMode && denyPerms.Any(f => Permission.Contains(f, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "演示模式 , 不允许操作" });
|
||||
context.Result = new JsonResult(new { code = (int)ResultCode.FORBIDDEN, msg = "演示模式 , 不允许操作" });
|
||||
}
|
||||
if (!HasPermi && !Permission.Equals("common"))
|
||||
{
|
||||
logger.Info($"用户{info.UserName}没有权限访问{url},当前权限[{Permission}]");
|
||||
JsonResult result = new(new ApiResult()
|
||||
{
|
||||
Code = (int)ResultCode.FORBIDDEN,
|
||||
Msg = $"你当前没有权限[{Permission}]访问,请联系管理员",
|
||||
Data = url
|
||||
})
|
||||
JsonResult result = new(new ApiResult((int)ResultCode.FORBIDDEN, $"你当前没有权限[{Permission}]访问,请联系管理员", url))
|
||||
{
|
||||
ContentType = "application/json",
|
||||
};
|
||||
+16
-20
@@ -2,20 +2,20 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Model;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using NLog;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Filters
|
||||
namespace ZR.ServiceCore.Middleware
|
||||
{
|
||||
public class GlobalActionMonitor : ActionFilterAttribute
|
||||
{
|
||||
static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
private ISysOperLogService OperLogService;
|
||||
private readonly ISysOperLogService OperLogService;
|
||||
public GlobalActionMonitor(ISysOperLogService operLogService)
|
||||
{
|
||||
OperLogService = operLogService;
|
||||
@@ -29,29 +29,25 @@ namespace ZR.Admin.WebApi.Filters
|
||||
/// <returns></returns>
|
||||
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
ApiResult response = new();
|
||||
response.Code = (int)ResultCode.PARAM_ERROR;
|
||||
|
||||
string msg = string.Empty;
|
||||
var values = context.ModelState.Values;
|
||||
foreach (var item in values)
|
||||
{
|
||||
foreach (var err in item.Errors)
|
||||
{
|
||||
if (err.ErrorMessage.Contains("JSON"))
|
||||
if (!string.IsNullOrEmpty(msg))
|
||||
{
|
||||
return next();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(response.Msg))
|
||||
{
|
||||
response.Msg += " | ";
|
||||
msg += " | ";
|
||||
}
|
||||
|
||||
response.Msg += err.ErrorMessage;
|
||||
msg += err.ErrorMessage;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(response.Msg))
|
||||
if (!string.IsNullOrEmpty(msg))
|
||||
{
|
||||
logger.Info($"请求参数错误,{response.Msg}");
|
||||
logger.Info($"请求参数错误,{msg}");
|
||||
ApiResult response = new((int)ResultCode.PARAM_ERROR, msg);
|
||||
|
||||
context.Result = new JsonResult(response);
|
||||
}
|
||||
return base.OnActionExecutionAsync(context, next);
|
||||
@@ -101,12 +97,12 @@ namespace ZR.Admin.WebApi.Filters
|
||||
OperUrl = HttpContextExtension.GetRequestUrl(context.HttpContext),
|
||||
RequestMethod = method,
|
||||
JsonResult = jsonResult,
|
||||
OperLocation = ip_info.Province + " " + ip_info.City,
|
||||
OperLocation = HttpContextExtension.GetIpInfo(ip),
|
||||
Method = controller + "." + action + "()",
|
||||
//Elapsed = _stopwatch.ElapsedMilliseconds,
|
||||
OperTime = DateTime.Now
|
||||
OperTime = DateTime.Now,
|
||||
OperParam = HttpContextExtension.GetRequestValue(context.HttpContext, method)
|
||||
};
|
||||
HttpContextExtension.GetRequestValue(context.HttpContext, sysOperLog);
|
||||
|
||||
if (logAttribute != null)
|
||||
{
|
||||
@@ -117,7 +113,7 @@ namespace ZR.Admin.WebApi.Filters
|
||||
}
|
||||
|
||||
LogEventInfo ei = new(NLog.LogLevel.Info, "GlobalActionMonitor", "");
|
||||
|
||||
|
||||
ei.Properties["jsonResult"] = !HttpMethods.IsGet(method) ? jsonResult : "";
|
||||
ei.Properties["requestParam"] = sysOperLog.OperParam;
|
||||
ei.Properties["user"] = userName;
|
||||
@@ -131,7 +127,7 @@ namespace ZR.Admin.WebApi.Filters
|
||||
}
|
||||
}
|
||||
|
||||
private LogAttribute? GetLogAttribute(ControllerActionDescriptor controllerActionDescriptor)
|
||||
private LogAttribute GetLogAttribute(ControllerActionDescriptor controllerActionDescriptor)
|
||||
{
|
||||
var attribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
|
||||
.FirstOrDefault(a => a.GetType().Equals(typeof(LogAttribute)));
|
||||
+28
-14
@@ -4,23 +4,18 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Framework;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Common;
|
||||
|
||||
//本命名空间暂时先不改,改动比较大2023年9月2日
|
||||
namespace ZR.Admin.WebApi.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// 授权校验访问
|
||||
/// 如果跳过授权登录在Action 或controller加上 AllowAnonymousAttribute
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class VerifyAttribute : Attribute, IAuthorizationFilter
|
||||
{
|
||||
static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// 只判断token是否正确,不判断权限
|
||||
/// 如果需要判断权限的在Action上加上ApiActionPermission属性标识权限类别,ActionPermissionFilter作权限处理
|
||||
@@ -40,16 +35,35 @@ namespace ZR.Admin.WebApi.Filters
|
||||
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
|
||||
string url = context.HttpContext.Request.Path;
|
||||
var isAuthed = context.HttpContext.User.Identity.IsAuthenticated;
|
||||
|
||||
string osType = context.HttpContext.Request.Headers["os"];
|
||||
//使用jwt token校验2020-11-21
|
||||
LoginUser info = JwtUtil.GetLoginUser(context.HttpContext);
|
||||
TokenModel loginUser = JwtUtil.GetLoginUser(context.HttpContext);
|
||||
if (loginUser != null)
|
||||
{
|
||||
var nowTime = DateTime.UtcNow;
|
||||
TimeSpan ts = loginUser.ExpireTime - nowTime;
|
||||
|
||||
if (info == null || !isAuthed)
|
||||
//Console.WriteLine($"jwt到期剩余:{ts.TotalMinutes}分,{ts.TotalSeconds}秒");
|
||||
|
||||
var CK = "token_" + loginUser.UserId;
|
||||
if (!CacheHelper.Exists(CK) && ts.TotalMinutes < 5)
|
||||
{
|
||||
var newToken = JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser));
|
||||
|
||||
CacheHelper.SetCache(CK, CK, 1);
|
||||
//移动端不加下面这个获取不到自定义Header
|
||||
if (osType != null)
|
||||
{
|
||||
context.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "X-Refresh-Token");
|
||||
}
|
||||
context.HttpContext.Response.Headers.Add("X-Refresh-Token", newToken);
|
||||
}
|
||||
}
|
||||
if (loginUser == null || !isAuthed)
|
||||
{
|
||||
string msg = $"请求访问[{url}]失败,无法访问系统资源";
|
||||
logger.Info($"{msg}");
|
||||
|
||||
context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg));
|
||||
//logger.Info(msg);
|
||||
context.Result = new JsonResult(ApiResult.Error(ResultCode.DENY, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
global using Newtonsoft.Json;
|
||||
global using SqlSugar;
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using Infrastructure.Extensions;
|
||||
+16
-14
@@ -2,17 +2,16 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Model;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using NLog;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
using textJson = System.Text.Json;
|
||||
|
||||
namespace ZR.Admin.WebApi.Middleware
|
||||
namespace ZR.ServiceCore.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局异常处理中间件
|
||||
@@ -45,16 +44,18 @@ namespace ZR.Admin.WebApi.Middleware
|
||||
|
||||
private async Task HandleExceptionAsync(HttpContext context, Exception ex)
|
||||
{
|
||||
NLog.LogLevel logLevel = NLog.LogLevel.Info;
|
||||
LogLevel logLevel = LogLevel.Info;
|
||||
int code = (int)ResultCode.GLOBAL_ERROR;
|
||||
string msg;
|
||||
string error = string.Empty;
|
||||
bool notice = true;
|
||||
//自定义异常
|
||||
if (ex is CustomException customException)
|
||||
{
|
||||
code = customException.Code;
|
||||
msg = customException.Message;
|
||||
error = customException.LogMsg;
|
||||
notice = customException.Notice;
|
||||
}
|
||||
else if (ex is ArgumentException)//参数异常
|
||||
{
|
||||
@@ -65,18 +66,18 @@ namespace ZR.Admin.WebApi.Middleware
|
||||
{
|
||||
msg = "服务器好像出了点问题,请联系系统管理员...";
|
||||
error = $"{ex.Message}";
|
||||
logLevel = NLog.LogLevel.Error;
|
||||
logLevel = LogLevel.Error;
|
||||
context.Response.StatusCode = 500;
|
||||
}
|
||||
var options = new JsonSerializerOptions
|
||||
var options = new textJson.JsonSerializerOptions
|
||||
{
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNamingPolicy = textJson.JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
ApiResult apiResult = new(code, msg);
|
||||
string responseResult = JsonSerializer.Serialize(apiResult, options).ToLower();
|
||||
string responseResult = textJson.JsonSerializer.Serialize(apiResult, options);
|
||||
string ip = HttpContextExtension.GetClientUserIp(context);
|
||||
var ip_info = IpTool.Search(ip);
|
||||
|
||||
@@ -90,9 +91,9 @@ namespace ZR.Admin.WebApi.Middleware
|
||||
ErrorMsg = string.IsNullOrEmpty(error) ? msg : error,
|
||||
OperName = HttpContextExtension.GetName(context),
|
||||
OperLocation = ip_info.Province + " " + ip_info.City,
|
||||
OperTime = DateTime.Now
|
||||
OperTime = DateTime.Now,
|
||||
OperParam = HttpContextExtension.GetRequestValue(context, context.Request.Method)
|
||||
};
|
||||
HttpContextExtension.GetRequestValue(context, sysOperLog);
|
||||
var endpoint = GetEndpoint(context);
|
||||
if (endpoint != null)
|
||||
{
|
||||
@@ -118,15 +119,16 @@ namespace ZR.Admin.WebApi.Middleware
|
||||
Logger.Log(ei);
|
||||
context.Response.ContentType = "text/json;charset=utf-8";
|
||||
await context.Response.WriteAsync(responseResult, System.Text.Encoding.UTF8);
|
||||
|
||||
|
||||
string errorMsg = $"> 操作人:{sysOperLog.OperName}" +
|
||||
$"\n> 操作地区:{sysOperLog.OperIp}({sysOperLog.OperLocation})" +
|
||||
$"\n> 操作模块:{sysOperLog.Title}" +
|
||||
$"\n> 操作地址:{sysOperLog.OperUrl}" +
|
||||
$"\n> 错误信息:{msg}\n\n> {error}";
|
||||
|
||||
WxNoticeHelper.SendMsg("系统出错", errorMsg, "", WxNoticeHelper.MsgType.markdown);
|
||||
|
||||
SysOperLogService.InsertOperlog(sysOperLog);
|
||||
if (!notice) return;
|
||||
WxNoticeHelper.SendMsg("系统异常", errorMsg, msgType: WxNoticeHelper.MsgType.markdown);
|
||||
}
|
||||
|
||||
public static Endpoint GetEndpoint(HttpContext context)
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZR.Model.System.Dto
|
||||
{
|
||||
public class LockUserDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
public string ConnnectionId { get; set; }
|
||||
public string Reason { get; set; }
|
||||
public int Time { get; set; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user