Merge remote-tracking branch 'zrorigin/master' into net7.0
# Conflicts: # ZR.Admin.WebApi/Controllers/System/SysLoginController.cs
This commit is contained in:
commit
de76f5872a
@ -1,5 +1,9 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
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;
|
||||
|
||||
@ -7,19 +11,35 @@ namespace Infrastructure
|
||||
{
|
||||
public static class App
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局配置文件
|
||||
/// </summary>
|
||||
public static OptionsSetting OptionsSetting => CatchOrDefault(() => ServiceProvider?.GetService<IOptions<OptionsSetting>>()?.Value);
|
||||
|
||||
/// <summary>
|
||||
/// 服务提供器
|
||||
/// </summary>
|
||||
public static IServiceProvider ServiceProvider => HttpContext?.RequestServices ?? InternalApp.ServiceProvider;
|
||||
public static IServiceProvider ServiceProvider => InternalApp.ServiceProvider;
|
||||
/// <summary>
|
||||
/// 获取请求上下文
|
||||
/// </summary>
|
||||
public static HttpContext HttpContext => HttpContextLocal.Current();
|
||||
public static HttpContext HttpContext => CatchOrDefault(() => ServiceProvider?.GetService<IHttpContextAccessor>()?.HttpContext);
|
||||
/// <summary>
|
||||
/// 获取请求上下文用户
|
||||
/// </summary>
|
||||
public static ClaimsPrincipal User => HttpContext?.User;
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户名
|
||||
/// </summary>
|
||||
public static string UserName => User?.Identity?.Name;
|
||||
/// <summary>
|
||||
/// 获取Web主机环境
|
||||
/// </summary>
|
||||
public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment;
|
||||
/// <summary>
|
||||
/// 获取全局配置
|
||||
/// </summary>
|
||||
public static IConfiguration Configuration => CatchOrDefault(() => InternalApp.Configuration, new ConfigurationBuilder().Build());
|
||||
/// <summary>
|
||||
/// 获取请求生命周期的服务
|
||||
/// </summary>
|
||||
@ -61,5 +81,25 @@ namespace Infrastructure
|
||||
{
|
||||
return ServiceProvider.GetRequiredService(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理获取对象异常问题
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="action">获取对象委托</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>T</returns>
|
||||
private static T CatchOrDefault<T>(Func<T> action, T defaultValue = null)
|
||||
where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
return action();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
public static class HttpContextLocal
|
||||
{
|
||||
private static Func<object> _asyncLocalAccessor;
|
||||
private static Func<object, object> _holderAccessor;
|
||||
private static Func<object, HttpContext> _httpContextAccessor;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前 HttpContext 对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static HttpContext Current()
|
||||
{
|
||||
var asyncLocal = (_asyncLocalAccessor ??= CreateAsyncLocalAccessor())();
|
||||
if (asyncLocal == null) return null;
|
||||
|
||||
var holder = (_holderAccessor ??= CreateHolderAccessor(asyncLocal))(asyncLocal);
|
||||
if (holder == null) return null;
|
||||
|
||||
return (_httpContextAccessor ??= CreateHttpContextAccessor(holder))(holder);
|
||||
|
||||
// 创建异步本地访问器
|
||||
static Func<object> CreateAsyncLocalAccessor()
|
||||
{
|
||||
var fieldInfo = typeof(HttpContextAccessor).GetField("_httpContextCurrent", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
var field = Expression.Field(null, fieldInfo);
|
||||
return Expression.Lambda<Func<object>>(field).Compile();
|
||||
}
|
||||
|
||||
// 创建常驻 HttpContext 访问器
|
||||
static Func<object, object> CreateHolderAccessor(object asyncLocal)
|
||||
{
|
||||
var holderType = asyncLocal.GetType().GetGenericArguments()[0];
|
||||
var method = typeof(AsyncLocal<>).MakeGenericType(holderType).GetProperty("Value").GetGetMethod();
|
||||
var target = Expression.Parameter(typeof(object));
|
||||
var convert = Expression.Convert(target, asyncLocal.GetType());
|
||||
var getValue = Expression.Call(convert, method);
|
||||
return Expression.Lambda<Func<object, object>>(getValue, target).Compile();
|
||||
}
|
||||
|
||||
// 获取 HttpContext 访问器
|
||||
static Func<object, HttpContext> CreateHttpContextAccessor(object holder)
|
||||
{
|
||||
var target = Expression.Parameter(typeof(object));
|
||||
var convert = Expression.Convert(target, holder.GetType());
|
||||
var field = Expression.Field(convert, "Context");
|
||||
var convertAsResult = Expression.Convert(field, typeof(HttpContext));
|
||||
return Expression.Lambda<Func<object, HttpContext>>(convertAsResult, target).Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,20 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
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";
|
||||
@ -58,10 +63,12 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// <returns></returns>
|
||||
protected IActionResult ExportExcel(string path, string fileName)
|
||||
{
|
||||
//IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
|
||||
//string fileDir = Path.Combine(webHostEnvironment.WebRootPath, path, fileName);
|
||||
|
||||
var stream = Io.File.OpenRead(path); //创建文件流
|
||||
//var webHostEnvironment = App.WebHostEnvironment;
|
||||
if (!Path.Exists(path))
|
||||
{
|
||||
throw new CustomException(fileName + "文件不存在");
|
||||
}
|
||||
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>
|
||||
///
|
||||
@ -169,23 +180,26 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// <summary>
|
||||
/// 下载导入模板
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="stream"></param>
|
||||
/// <typeparam name="T">数据类型</typeparam>
|
||||
/// <param name="list">空数据类型集合</param>
|
||||
/// <param name="fileName">下载文件名</param>
|
||||
/// <returns></returns>
|
||||
protected string DownloadImportTemplate<T>(List<T> list, Stream stream, string fileName)
|
||||
protected (string, string) DownloadImportTemplate<T>(List<T> list, string fileName)
|
||||
{
|
||||
IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
|
||||
string sFileName = $"{fileName}模板.xlsx";
|
||||
string newFileName = Path.Combine(webHostEnvironment.WebRootPath, "ImportTemplate", sFileName);
|
||||
IWebHostEnvironment webHostEnvironment = App.WebHostEnvironment;
|
||||
string sFileName = $"{fileName}.xlsx";
|
||||
string fullPath = Path.Combine(webHostEnvironment.WebRootPath, "ImportTemplate", sFileName);
|
||||
|
||||
if (!Directory.Exists(newFileName))
|
||||
//不存在模板创建模板
|
||||
if (!Directory.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(newFileName));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
|
||||
}
|
||||
MiniExcel.SaveAs(newFileName, list);
|
||||
return sFileName;
|
||||
if (!Path.Exists(fullPath))
|
||||
{
|
||||
MiniExcel.SaveAs(fullPath, list, overwriteFile: true);
|
||||
}
|
||||
return (sFileName, fullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -2,7 +2,7 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ZR.Admin.WebApi.Framework
|
||||
namespace Infrastructure.Converter
|
||||
{
|
||||
public class JsonConverterUtil
|
||||
{
|
||||
@ -29,7 +29,7 @@ namespace ZR.Admin.WebApi.Framework
|
||||
|
||||
public static DateTime? ParseDateTime(string dateStr)
|
||||
{
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(dateStr, @"^\d{4}[/-]") && DateTime.TryParse(dateStr, null,System.Globalization.DateTimeStyles.AssumeLocal, out var dateVal))
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(dateStr, @"^\d{4}[/-]") && DateTime.TryParse(dateStr, null, System.Globalization.DateTimeStyles.AssumeLocal, out var dateVal))
|
||||
return dateVal;
|
||||
return null;
|
||||
}
|
||||
48
Infrastructure/Converter/StringConverter.cs
Normal file
48
Infrastructure/Converter/StringConverter.cs
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Infrastructure
|
||||
namespace Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局静态常量
|
||||
/// </summary>
|
||||
public class GlobalConstant
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成常量
|
||||
/// </summary>
|
||||
public static readonly string CodeGenDbConfig;
|
||||
|
||||
/// <summary>
|
||||
/// 管理员权限
|
||||
/// </summary>
|
||||
|
||||
@ -91,7 +91,7 @@ namespace Infrastructure
|
||||
|
||||
#region 获取unix时间戳
|
||||
/// <summary>
|
||||
/// 获取unix时间戳
|
||||
/// 获取unix时间戳(毫秒)
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
/// <returns></returns>
|
||||
@ -100,6 +100,12 @@ namespace Infrastructure
|
||||
long unixTime = ((DateTimeOffset)dt).ToUnixTimeMilliseconds();
|
||||
return unixTime;
|
||||
}
|
||||
|
||||
public static long GetUnixTimeSeconds(DateTime dt)
|
||||
{
|
||||
long unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();
|
||||
return unixTime;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 获取日期天的最小时间
|
||||
|
||||
@ -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>
|
||||
<Compile Remove="Model\PagedInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspectCore.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
||||
<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.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -1,6 +1,5 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
|
||||
namespace Infrastructure
|
||||
@ -15,12 +14,12 @@ namespace Infrastructure
|
||||
/// <summary>
|
||||
/// 全局配置构建器
|
||||
/// </summary>
|
||||
//public static IConfigurationBuilder ConfigurationBuilder;
|
||||
public static IConfiguration Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// 获取Web主机环境
|
||||
/// </summary>
|
||||
//internal static IWebHostEnvironment WebHostEnvironment;
|
||||
public static IWebHostEnvironment WebHostEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 获取泛型主机环境
|
||||
|
||||
@ -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>()
|
||||
{
|
||||
14
Infrastructure/Log.cs
Normal file
14
Infrastructure/Log.cs
Normal file
@ -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,23 +1,31 @@
|
||||
|
||||
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; }
|
||||
public JwtSettings JwtSettings { get; set; }
|
||||
public Gen Gen { get; set; }
|
||||
public List<DbConfigs> DbConfigs { get; set; }
|
||||
public DbConfigs CodeGenDbConfig { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 发送邮件数据配置
|
||||
@ -76,11 +84,24 @@ 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
|
||||
{
|
||||
public string Database { get; set; }
|
||||
public bool ShowApp { get; set; }
|
||||
public bool AutoPre { get; set; }
|
||||
public string VuePath { get; set; }
|
||||
public string Author { get; set; }
|
||||
public DbConfigs GenDbConfig { get; set; }
|
||||
public CsharpTypeArr CsharpTypeArr { get; set; }
|
||||
}
|
||||
|
||||
public class DbConfigs
|
||||
@ -89,10 +110,17 @@ namespace Infrastructure
|
||||
public int DbType { get; set; }
|
||||
public string ConfigId { get; set; }
|
||||
public bool IsAutoCloseConnection { get; set; }
|
||||
/// <summary>
|
||||
/// 是否代码生成使用库
|
||||
/// </summary>
|
||||
public bool IsGenerateDb { get; set; }
|
||||
public string DbName { get; set; }
|
||||
}
|
||||
|
||||
public class CsharpTypeArr
|
||||
{
|
||||
public string[] String { get; set; }
|
||||
public string[] Int { get; set; }
|
||||
public string[] Long { get; set; }
|
||||
public string[] DateTime { get; set; }
|
||||
public string[] Float { get; set; }
|
||||
public string[] Decimal { get; set; }
|
||||
public string[] Bool { get; set; }
|
||||
}
|
||||
}
|
||||
48
Infrastructure/Model/TokenModel.cs
Normal file
48
Infrastructure/Model/TokenModel.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -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服务注册
|
||||
@ -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>
|
||||
@ -9,7 +16,7 @@
|
||||
/// <param name="configuration"></param>
|
||||
public static void AddCors(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var corsUrls = configuration["corsUrls"]?.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
var corsUrls = configuration.GetSection("corsUrls").Get<string[]>();
|
||||
|
||||
//配置跨域
|
||||
services.AddCors(c =>
|
||||
41
Infrastructure/WebExtensions/EntityExtension.cs
Normal file
41
Infrastructure/WebExtensions/EntityExtension.cs
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
using Infrastructure.Extensions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
public static class EntityExtension
|
||||
{
|
||||
public static TSource ToCreate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null || context == null) return source;
|
||||
BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
|
||||
|
||||
types.GetProperty("CreateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("AddTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("CreateBy", flag)?.SetValue(source, context.GetName(), null);
|
||||
types.GetProperty("Create_by", flag)?.SetValue(source, context.GetName(), null);
|
||||
types.GetProperty("UserId", flag)?.SetValue(source, context.GetUId(), null);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
public static TSource ToUpdate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null || context == null) return source;
|
||||
BindingFlags flag = BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance;
|
||||
|
||||
types.GetProperty("UpdateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("Update_time", flag)?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("UpdateBy", flag)?.SetValue(source, context.GetName(), null);
|
||||
types.GetProperty("Update_by", flag)?.SetValue(source, context.GetName(), null);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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,6 +134,55 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
return context.Request.Headers["Authorization"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求Url
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetRequestUrl(this HttpContext context)
|
||||
{
|
||||
return context != null ? context.Request.Path.Value : "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求参数
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetQueryString(this HttpContext context)
|
||||
{
|
||||
return context != null ? context.Request.QueryString.Value : "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取body请求参数
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetBody(this HttpContext context)
|
||||
{
|
||||
context.Request.EnableBuffering();
|
||||
//context.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
//using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
|
||||
////需要使用异步方式才能获取
|
||||
//return reader.ReadToEndAsync().Result;
|
||||
string body = string.Empty;
|
||||
var buffer = new MemoryStream();
|
||||
context.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
context.Request.Body.CopyToAsync(buffer);
|
||||
buffer.Position = 0;
|
||||
try
|
||||
{
|
||||
using StreamReader streamReader = new(buffer, Encoding.UTF8);
|
||||
body = streamReader.ReadToEndAsync().Result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer?.Dispose();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
@ -146,55 +198,36 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求Url
|
||||
/// 根据IP获取地理位置
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetRequestUrl(this HttpContext context)
|
||||
public static string GetIpInfo(string IP)
|
||||
{
|
||||
return context != null ? context.Request.Path.Value : "";
|
||||
var ipInfo = IpTool.Search(IP);
|
||||
return ipInfo?.Province + "-" + ipInfo?.City + "-" + ipInfo?.NetworkOperator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求参数
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetQueryString(this HttpContext context)
|
||||
{
|
||||
return context != null ? context.Request.QueryString.Value : "";
|
||||
}
|
||||
/// <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 param = string.Empty;
|
||||
|
||||
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod) || HttpMethods.IsDelete(reqMethod))
|
||||
{
|
||||
context.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
|
||||
//需要使用异步方式才能获取
|
||||
param = reader.ReadToEndAsync().Result;
|
||||
if (param.IsEmpty())
|
||||
{
|
||||
param = context.GetQueryString();
|
||||
}
|
||||
param = PwdRep().Replace(param, "***");
|
||||
param = context.GetBody();
|
||||
string regex = "(?<=\"password\":\")[^\",]*";
|
||||
param = Regex.Replace(param, regex, "***");
|
||||
}
|
||||
else
|
||||
if (param.IsEmpty())
|
||||
{
|
||||
param = context.GetQueryString();
|
||||
}
|
||||
operLog.OperParam = param;
|
||||
return param;
|
||||
}
|
||||
|
||||
[GeneratedRegex("(?<=\"password\":\")[^\",]*")]
|
||||
private static partial Regex PwdRep();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
39
Infrastructure/WebExtensions/JwtExtension.cs
Normal file
39
Infrastructure/WebExtensions/JwtExtension.cs
Normal file
@ -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;
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Infrastructure/WebExtensions/LogoExtension.cs
Normal file
25
Infrastructure/WebExtensions/LogoExtension.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using Infrastructure.Helper;
|
||||
using JinianNet.JNTemplate;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace Infrastructure
|
||||
{
|
||||
public static class LogoExtension
|
||||
{
|
||||
public static void AddLogo(this IServiceCollection services)
|
||||
{
|
||||
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/h5");
|
||||
Console.WriteLine($"Swagger地址:[后端启动地址]/swagger/index.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Infrastructure/ZR.Infrastructure.csproj
Normal file
26
Infrastructure/ZR.Infrastructure.csproj
Normal file
@ -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>
|
||||
199
README.en.md
Normal file
199
README.en.md
Normal file
@ -0,0 +1,199 @@
|
||||
<h2 align="center"> ZR.Admin.NET Back-end management system</h2>
|
||||
<h4 align="center">base .Net7 + vue2.x/vue3.x/uniapp Front-end and back-end separation of .NET rapid development framework</h4>
|
||||
|
||||
<p align="center">
|
||||
<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/更新日志-20230920-yellow"/></a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<p><strong><a href="README.md">简体中文</a> | <a href="README.en.md">English</a></strong></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 🍟 overview
|
||||
|
||||
- This project is suitable for developers with some NetCore and vue foundation
|
||||
-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)
|
||||
|
||||
```
|
||||
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! ~
|
||||
```
|
||||
|
||||
## 🍿 Online experience
|
||||
|
||||
- Official documentation:http://www.izhaorui.cn/doc
|
||||
- Join a group chat:[立即加入](http://www.izhaorui.cn/doc/contact.html)
|
||||
- Vue3.x experience:[http://www.izhaorui.cn/vue3](http://www.izhaorui.cn/vue3)
|
||||
- Vue2.x experience:[http://www.izhaorui.cn/admin](http://www.izhaorui.cn/admin)
|
||||
- Uniapp experience:[http://www.izhaorui.cn/h5](http://www.izhaorui.cn/h5)
|
||||
- account/password:admin/123456
|
||||
|
||||
| H5 | WeChat mini program |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
|  |  |
|
||||
|
||||
```
|
||||
Since it is a personal project, the funds are limited, and the experience server is low-fied, please cherish it, poke it lightly, and appreciate it!!
|
||||
```
|
||||
|
||||
## 💒 Code repository
|
||||
|
||||
| repository | Github | Gitee |
|
||||
| -------------- | ------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| 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
|
||||
|
||||
Vue Front-end technology stack: Based on Vue2.x/Vue3.x/UniApp, Vue, Vue-router, Vue-CLI, AXIOS, Element-UI, Echats, i18N Internationalization, etc., the front-end adopts VSCODE tool development
|
||||
|
||||
## 🍀 Back-end technology
|
||||
|
||||
- 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
|
||||
- Tools: Captcha, rich public functions
|
||||
- Interface throttling: Supports interface throttling to avoid excessive pressure on the service layer caused by malicious requests
|
||||
- Code generation: efficient development, the code generator can generate all front-end and back-end code with one click
|
||||
- Data dictionary: Support data dictionary, which can facilitate the management of some states
|
||||
- Sharding and sharding: Using ORM SQLSUGAR, you can easily achieve superior sharding and sharding performance
|
||||
- Multi-tenant: Support multi-tenancy function
|
||||
- Cache data: Built-in memory cache and Redis
|
||||
|
||||
## 🍖 Built-in features
|
||||
|
||||
1. User management: The user is the system operator, and this function mainly completes the system user configuration.
|
||||
2. Department management: configure the system organization (company, department, group), tree structure display.
|
||||
3. Job management: configure the position of the system user.
|
||||
4. Menu management: configure system menus, operation permissions, button permission identification, etc.
|
||||
5. Role Management: Role menu permission assignment.
|
||||
6. Dictionary management: maintain some relatively fixed data that is often used in the system.
|
||||
7. Operation log: system normal operation log records and queries; System exception information logging and querying.
|
||||
8. Logon logon: The system logon log record query contains logon exceptions.
|
||||
9. System Interface: Use Swagger to generate relevant API interface documentation.
|
||||
10. Service monitoring: Monitor the current system CPU, memory, disk, stack, and other related information.
|
||||
11. Online Builder: Drag form elements to generate the corresponding VUE code (only VUE2 supported).
|
||||
12. Task system: Based on the Quartz.NET, you can schedule tasks online (add, modify, delete, manually execute) including execution result logs.
|
||||
13. Article management: You can write article records.
|
||||
14. Code generation: You can generate front-end and back-end code (.cs, .vue, .js, .sql, etc.) with one click, support download, customize the configuration of front-end display controls, and make development faster and more efficient (the strongest in history).
|
||||
15. Parameter management: dynamically configure common parameters for the system.
|
||||
16. Send Mail: You can send mail to multiple users.
|
||||
17. File management: You can manage uploaded files, which currently supports uploading to on-premises and Alibaba Cloud.
|
||||
18. Notification management: The system notifies and announces information release and maintenance, and uses SignalR to realize real-time notification to users.
|
||||
19. Account Registration: You can register an account to log in to the system.
|
||||
20. Multi-language management: support static and back-end dynamic configuration internationalization. Currently only supports Chinese, English, and Traditional characters (only VUE3 is supported)
|
||||
|
||||
## 🍻 Project structure
|
||||
|
||||
```
|
||||
├─ZR.Service ->[你的业务服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.ServiceCore ->[系统服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Repository ->[仓库层类库]:方便提供有执行存储过程的操作;
|
||||
├─ZR.Model ->[实体层类库]:提供项目中的数据库表、数据传输对象;
|
||||
├─ZR.Admin.WebApi ->[webapi接口]:为Vue版或其他三方系统提供接口服务。
|
||||
├─ZR.Tasks ->[定时任务类库]:提供项目定时任务实现功能;
|
||||
├─ZR.CodeGenerator ->[代码生成功能]:包含代码生成的模板、方法、代码生成的下载。
|
||||
├─ZR.Vue ->[前端UI]:vue2.0版本UI层(已经不再更新推荐使用vue3)。
|
||||
├─document ->[文档]:数据库脚本
|
||||
```
|
||||
|
||||
## 🍎 Storyplate
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/1.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/2.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/3.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/4.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/5.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/6.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/7.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/8.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/9.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/10.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/11.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/12.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/13.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/14.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/15.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/16.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/17.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/18.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/19.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/20.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Mobile Storyplate
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a1.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a2.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a8.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a4.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a5.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a6.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a7.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a9.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a10.png"/></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
## 🎉 Advantages
|
||||
|
||||
1. The front-end system does not need to write login, authorization, and authentication modules; Just write the business module
|
||||
2. The background system can be used directly after release without any secondary development
|
||||
3. The front-end and back-end systems are separated, and they are separate systems (domain names can be independent)
|
||||
4. Unified handling of global exceptions
|
||||
5. Custom code generation features
|
||||
6. Less dependence, easy to get started
|
||||
7. Comprehensive documentation
|
||||
|
||||
## 💐 Special thanks
|
||||
|
||||
- 👉Ruoyi.vue:[Ruoyi](http://www.ruoyi.vip/)
|
||||
- 👉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)
|
||||
|
||||
## 🎀 donation
|
||||
|
||||
If you feel that the project has helped you, you can ask the author for a cup of coffee as a sign of encouragement ☕️
|
||||
<img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/pay.jpg"/>
|
||||
67
README.md
67
README.md
@ -1,13 +1,21 @@
|
||||
<h2 align="center"> ZR.Admin.NET后台管理系统</h2>
|
||||
<h4 align="center">基于.NET5/.Net7 + vue2.x/vue3.x/uniapp前后端分离的.net快速开发框架</h4>
|
||||
<h4 align="center">基于.Net7 + vue2.x/vue3.x/uniapp前后端分离的.net快速开发框架</h4>
|
||||
|
||||
<p align="center">
|
||||
<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/change-更新日志-yellow"/></a>
|
||||
<a href="http://www.izhaorui.cn/doc/changelog.html"><img src="https://img.shields.io/badge/更新日志-20230920-yellow"/></a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<p><strong><a href="README.md">简体中文</a> | <a href="README.en.md">English</a></strong></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 🍟 概述
|
||||
|
||||
- 本项目适合有一定 NetCore 和 vue 基础的开发人员
|
||||
@ -20,7 +28,7 @@
|
||||
- 阿里云特惠专区:[☛☛ 点我进入 ☚☚](https://www.aliyun.com/minisite/goods?userCode=uotn5vt1&share_source=copy_link)
|
||||
|
||||
```
|
||||
如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,这样作者才有继续免费下去的动力,谢谢!~
|
||||
如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,谢谢!~
|
||||
```
|
||||
|
||||
## 🍿 在线体验
|
||||
@ -30,26 +38,26 @@
|
||||
- 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 | 微信小程序 |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
```
|
||||
由于是个人项目,资金有限,体验服是低配,请大家爱惜,轻戳,不胜感激!!!
|
||||
由于是个人项目,资金有限,体验服务器是低配,请大家爱惜,轻戳,不胜感激!!!
|
||||
```
|
||||
|
||||
## 💒 代码仓库
|
||||
|
||||
| 仓库 | Github | Gitee |
|
||||
| ---- | ------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| Net7 | [克隆/下载](https://github.com/izhaorui/Zr.Admin.NET) | [克隆/下载](https://gitee.com/izory/ZrAdminNetCore/tree/net7.0/) |
|
||||
| Vue3 | [克隆/下载](https://github.com/izhaorui/ZR.Admin.Vue3) | [克隆/下载](https://gitee.com/izory/ZRAdmin-vue) |
|
||||
| 仓库 | Github | Gitee |
|
||||
| -------------- | ------------------------------------------------------ | --------------------------------------------------- |
|
||||
| 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) |
|
||||
|
||||
## 🍁 前端技术
|
||||
|
||||
Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli 、axios、 element-ui、echats、i18n 国际化等,前端采用 vscode 工具开发
|
||||
Vue 版前端技术栈 :基于 vue2.x/vue3.x/uniapp、vuex、vue-router 、vue-cli 、axios、 element-ui、echats、i18n 国际化等,前端采用 vscode 工具开发
|
||||
|
||||
## 🍀 后端技术
|
||||
|
||||
@ -64,6 +72,7 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
- 分库分表:使用 orm sqlsugar 可以很轻松的实现分库分库性能优越
|
||||
- 多 租 户:支持多租户功能
|
||||
- 缓存数据:内置内存缓存和 Redis
|
||||
- signalR:使用 signalr 管理用户在线状态
|
||||
|
||||
## 🍖 内置功能
|
||||
|
||||
@ -80,24 +89,30 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
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.Repository ->[仓库层类库]:方便提供有执行存储过程的操作;
|
||||
├─ZR.Model ->[实体层类库]:提供项目中的数据库表、数据传输对象;
|
||||
├─ZR.Admin.WebApi ->[webapi接口]:为Vue版或其他三方系统提供接口服务。
|
||||
├─ZR.Service ->[你的业务服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.ServiceCore ->[系统服务层类库]:提供WebApi接口调用;
|
||||
├─ZR.Repository ->[仓库层类库]:方便提供有执行存储过程的操作;
|
||||
├─ZR.Model ->[实体层类库]:提供项目中的数据库表、数据传输对象;
|
||||
├─ZR.Admin.WebApi ->[webapi接口]:为Vue版或其他三方系统提供接口服务。
|
||||
├─ZR.Tasks ->[定时任务类库]:提供项目定时任务实现功能;
|
||||
├─ZR.CodeGenerator ->[代码生成功能]:包含代码生成的模板、方法、代码生成的下载。
|
||||
├─ZR.Vue ->[前端UI]:vue2.0版本UI层。
|
||||
├─ZR.CodeGenerator ->[代码生成功能]:包含代码生成的模板、方法、代码生成的下载。
|
||||
├─ZR.Vue ->[前端UI]:vue2.0版本UI层(已经不再更新推荐使用vue3)。
|
||||
├─document ->[文档]:数据库脚本
|
||||
```
|
||||
|
||||
@ -138,12 +153,15 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/17.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/18.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/18.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/19.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/20.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/21.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 移动端演示图
|
||||
@ -160,6 +178,13 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a5.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a6.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a7.png"/></td>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a9.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/a10.png"/></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
@ -173,6 +198,7 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
5. 自定义的代码生成功能
|
||||
6. 依赖少,上手容易
|
||||
7. 文档全面
|
||||
8. 支持中文表头导入数据
|
||||
|
||||
## 💐 特别鸣谢
|
||||
|
||||
@ -180,8 +206,9 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x、vuex、vue-router 、vue-cli
|
||||
- 👉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)
|
||||
|
||||
## 🎀 捐赠
|
||||
|
||||
如果你觉得这个项目帮助到了你,你可以请作者喝杯咖啡表示鼓励 ☕️
|
||||
<img src="https://gitee.com/izory/ZrAdminNetCore/raw/net7.0/document/images/pay.jpg"/>
|
||||
<img src="https://gitee.com/izory/ZrAdminNetCore/raw/master/document/images/pay.jpg"/>
|
||||
|
||||
@ -1,15 +1,9 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
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.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.IService;
|
||||
using ZR.Service.System;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
@ -19,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;
|
||||
@ -26,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("/")]
|
||||
@ -48,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>
|
||||
|
||||
@ -1,15 +1,9 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Model.Dto;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Service.System.IService;
|
||||
using ZR.Model.Dto;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
@ -17,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// 文章目录Controller
|
||||
/// </summary>
|
||||
[Route("article/ArticleCategory")]
|
||||
[ApiExplorerSettings(GroupName = "article")]
|
||||
public class ArticleCategoryController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@ -65,7 +60,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
public IActionResult GetArticleCategory(int CategoryId)
|
||||
{
|
||||
var response = _ArticleCategoryService.GetFirst(x => x.CategoryId == CategoryId);
|
||||
|
||||
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
@ -17,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("article")]
|
||||
[ApiExplorerSettings(GroupName = "article")]
|
||||
public class ArticleController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@ -36,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);
|
||||
@ -91,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,19 +1,11 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using IP2Region.Ex.Models;
|
||||
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;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Model.System.Generate;
|
||||
using ZR.Service.System.IService;
|
||||
@ -25,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();
|
||||
@ -153,7 +146,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
throw new CustomException("表不能为空");
|
||||
}
|
||||
var dbConfig = AppSettings.Get<List<DbConfigs>>("dbConfigs").FirstOrDefault(f => f.IsGenerateDb);
|
||||
DbConfigs dbConfig = AppSettings.Get<DbConfigs>(nameof(GlobalConstant.CodeGenDbConfig));
|
||||
string[] tableNames = tables.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
int result = 0;
|
||||
foreach (var tableName in tableNames)
|
||||
@ -218,29 +211,25 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// <summary>
|
||||
/// 预览代码
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="tableId"></param>
|
||||
/// <param name="VueVersion"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("preview/{tableId}")]
|
||||
[ActionPermissionFilter(Permission = "tool:gen:preview")]
|
||||
public IActionResult Preview(long tableId = 0, int VueVersion = 0)
|
||||
public IActionResult Preview([FromQuery] GenerateDto dto, [FromRoute] int tableId = 0)
|
||||
{
|
||||
GenerateDto dto = new()
|
||||
{
|
||||
TableId = tableId,
|
||||
VueVersion = VueVersion
|
||||
};
|
||||
dto.TableId = tableId;
|
||||
if (dto == null || dto.TableId <= 0)
|
||||
{
|
||||
throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空");
|
||||
}
|
||||
var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId);
|
||||
var dbConfig = AppSettings.Get<List<DbConfigs>>("dbConfigs").FirstOrDefault(f => f.IsGenerateDb);
|
||||
var dbConfig = AppSettings.Get<DbConfigs>(nameof(GlobalConstant.CodeGenDbConfig));
|
||||
|
||||
dto.DbType = dbConfig.DbType;
|
||||
dto.GenTable = genTableInfo;
|
||||
dto.IsPreview = true;
|
||||
//生成代码
|
||||
|
||||
CodeGeneratorTool.Generate(dto);
|
||||
|
||||
return SUCCESS(dto.GenCodes);
|
||||
@ -261,7 +250,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空");
|
||||
}
|
||||
var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId);
|
||||
var dbConfig = AppSettings.Get<List<DbConfigs>>("dbConfigs").FirstOrDefault(f => f.IsGenerateDb);
|
||||
var dbConfig = AppSettings.Get<DbConfigs>(nameof(GlobalConstant.CodeGenDbConfig));
|
||||
|
||||
dto.DbType = dbConfig.DbType;
|
||||
dto.GenTable = genTableInfo;
|
||||
@ -284,12 +273,20 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
|
||||
//生成代码到指定文件夹
|
||||
CodeGeneratorTool.Generate(dto);
|
||||
//下载文件
|
||||
FileUtil.ZipGenCode(dto.ZipPath, dto.GenCodePath, zipReturnFileName);
|
||||
if (genTableInfo.Options.GenerateMenu)
|
||||
{
|
||||
SysMenuService.AddSysMenu(genTableInfo, dto.ReplaceDto.PermissionPrefix, dto.ReplaceDto.ShowBtnEdit, dto.ReplaceDto.ShowBtnExport);
|
||||
SysMenuService.AddSysMenu(genTableInfo, dto.ReplaceDto.PermissionPrefix, dto.ReplaceDto.ShowBtnEdit, dto.ReplaceDto.ShowBtnExport, dto.ReplaceDto.ShowBtnImport);
|
||||
}
|
||||
|
||||
foreach (var item in dto.GenCodes)
|
||||
{
|
||||
item.Path = Path.Combine(dto.GenCodePath, item.Path);
|
||||
FileUtil.WriteAndSave(item.Path, item.Content);
|
||||
}
|
||||
|
||||
//下载文件
|
||||
FileUtil.ZipGenCode(dto.ZipPath, dto.GenCodePath, zipReturnFileName);
|
||||
|
||||
return SUCCESS(new { path = "/Generatecode/" + zipReturnFileName, fileName = dto.ZipFileName });
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model;
|
||||
using ZR.Model.Dto;
|
||||
using ZR.Model.Models;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
@ -19,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/CommonLang")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class CommonLangController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@ -135,6 +131,25 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
return ToResponse(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除多语言配置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("ByKey")]
|
||||
[ActionPermissionFilter(Permission = "system:lang:delete")]
|
||||
[Log(Title = "多语言配置", BusinessType = BusinessType.DELETE)]
|
||||
public IActionResult DeleteCommonLangByKey(string langkey)
|
||||
{
|
||||
if (langkey.IsEmpty()) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); }
|
||||
|
||||
var response = _CommonLangService
|
||||
.Deleteable()
|
||||
.EnableDiffLogEvent()
|
||||
.Where(f => f.LangKey == langkey)
|
||||
.ExecuteCommand();
|
||||
return ToResponse(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出多语言配置
|
||||
/// </summary>
|
||||
@ -145,11 +160,50 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
public IActionResult Export([FromQuery] CommonLangQueryDto parm)
|
||||
{
|
||||
parm.PageSize = 10000;
|
||||
var list = _CommonLangService.GetList(parm).Result;
|
||||
var list = _CommonLangService.GetListToPivot(parm);
|
||||
|
||||
string sFileName = ExportExcel(list, "CommonLang", "多语言配置");
|
||||
return SUCCESS(new { path = "/export/" + sFileName, fileName = sFileName });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入
|
||||
/// </summary>
|
||||
/// <param name="formFile"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("importData")]
|
||||
[Log(Title = "多语言设置导入", BusinessType = BusinessType.IMPORT, IsSaveRequestData = false, IsSaveResponseData = true)]
|
||||
[ActionPermissionFilter(Permission = "system:lang:import")]
|
||||
public IActionResult ImportData([FromForm(Name = "file")] IFormFile formFile)
|
||||
{
|
||||
List<CommonLang> list = new();
|
||||
var nowTime = DateTime.Now;
|
||||
using (var stream = formFile.OpenReadStream())
|
||||
{
|
||||
var rows = stream.Query(startCell: "A2").ToList();
|
||||
|
||||
foreach (var item in rows)
|
||||
{
|
||||
list.Add(new CommonLang() { LangCode = "zh-cn", LangKey = item.A, LangName = item.B, Addtime = nowTime });
|
||||
list.Add(new CommonLang() { LangCode = "en", LangKey = item.A, LangName = item.C, Addtime = nowTime });
|
||||
list.Add(new CommonLang() { LangCode = "zh-tw", LangKey = item.A, LangName = item.D, Addtime = nowTime });
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS(_CommonLangService.ImportCommonLang(list));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 多语言设置导入模板下载
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("importTemplate")]
|
||||
[Log(Title = "多语言设置模板", BusinessType = BusinessType.EXPORT, IsSaveRequestData = true, IsSaveResponseData = false)]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ImportTemplateExcel()
|
||||
{
|
||||
var result = DownloadImportTemplate(new List<CommonLang>() { }, "lang");
|
||||
return ExportExcel(result.Item2, result.Item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,8 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
@ -21,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/config")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysConfigController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers.System
|
||||
@ -16,6 +12,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/dept")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysDeptController : BaseController
|
||||
{
|
||||
public ISysDeptService DeptService;
|
||||
@ -33,7 +30,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <returns></returns>
|
||||
[ActionPermissionFilter(Permission = "system:dept:list")]
|
||||
[HttpGet("list")]
|
||||
public IActionResult List([FromQuery] SysDept dept)
|
||||
public IActionResult List([FromQuery] SysDeptQueryDto dept)
|
||||
{
|
||||
return SUCCESS(DeptService.GetSysDepts(dept), TIME_FORMAT_FULL);
|
||||
}
|
||||
@ -46,7 +43,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
[HttpGet("list/exclude/{deptId}")]
|
||||
public IActionResult ExcludeChild(long deptId)
|
||||
{
|
||||
var depts = DeptService.GetSysDepts(new SysDept());
|
||||
var depts = DeptService.GetSysDepts(new SysDeptQueryDto());
|
||||
|
||||
for (int i = 0; i < depts.Count; i++)
|
||||
{
|
||||
@ -66,7 +63,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <param name="dept"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("treeselect")]
|
||||
public IActionResult TreeSelect(SysDept dept)
|
||||
public IActionResult TreeSelect(SysDeptQueryDto dept)
|
||||
{
|
||||
var depts = DeptService.GetSysDepts(dept);
|
||||
|
||||
@ -82,7 +79,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
[HttpGet("roleDeptTreeselect/{roleId}")]
|
||||
public IActionResult RoleMenuTreeselect(int roleId)
|
||||
{
|
||||
var depts = DeptService.GetSysDepts(new SysDept());
|
||||
var depts = DeptService.GetSysDepts(new SysDeptQueryDto());
|
||||
var checkedKeys = DeptService.SelectRoleDepts(roleId);
|
||||
return SUCCESS(new
|
||||
{
|
||||
@ -152,7 +149,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
[Log(Title = "部门管理", BusinessType = BusinessType.DELETE)]
|
||||
public IActionResult Remove(long deptId)
|
||||
{
|
||||
if (DeptService.Queryable().Count(it => it.ParentId == deptId && it.DelFlag == "0") > 0)
|
||||
if (DeptService.Queryable().Count(it => it.ParentId == deptId && it.DelFlag == 0) > 0)
|
||||
{
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, $"存在下级部门,不允许删除");
|
||||
}
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
@ -16,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;
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
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("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,20 +1,7 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Model;
|
||||
using IPTools.Core;
|
||||
using Lazy.Captcha.Core;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Lazy.Captcha.Core;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NETCore.Encrypt;
|
||||
using UAParser;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Admin.WebApi.Framework;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System;
|
||||
@ -25,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;
|
||||
@ -36,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,
|
||||
@ -47,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;
|
||||
@ -57,11 +45,9 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
this.permissionService = permissionService;
|
||||
this.sysConfigService = configService;
|
||||
roleService = sysRoleService;
|
||||
this.jwtSettings = jwtSettings.Value;
|
||||
this.optionSettings = optionSettings.Value;
|
||||
}
|
||||
|
||||
// RSA私钥
|
||||
private static string _privateKey;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
@ -80,17 +66,18 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
|
||||
}
|
||||
// RSA解密
|
||||
loginBody.Password = EncryptProvider.RSADecryptWithPem(_privateKey, loginBody.Password);
|
||||
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>
|
||||
@ -130,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 });
|
||||
}
|
||||
|
||||
@ -164,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>
|
||||
@ -193,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");
|
||||
@ -206,7 +172,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
|
||||
}
|
||||
|
||||
|
||||
SysUser user = sysUserService.Register(dto);
|
||||
if (user.UserId > 0)
|
||||
{
|
||||
@ -214,19 +180,86 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
}
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员");
|
||||
}
|
||||
|
||||
|
||||
#region 二维码登录
|
||||
|
||||
/// <summary>
|
||||
/// 获取RSA公钥和密钥
|
||||
/// 生成二维码
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="deviceId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("getRsaKey")]
|
||||
public IActionResult GetRsaKey()
|
||||
[HttpGet("/GenerateQrcode")]
|
||||
public IActionResult GenerateQrcode(string uuid, string deviceId)
|
||||
{
|
||||
var (publicPem, privatePem) = EncryptProvider.RSAToPem(true);
|
||||
_privateKey = privatePem;
|
||||
return SUCCESS(new {
|
||||
PublicKey = publicPem
|
||||
});
|
||||
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,10 +1,4 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@ -17,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,19 +1,12 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Constant;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
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.Common;
|
||||
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
|
||||
{
|
||||
@ -22,6 +15,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/notice")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysNoticeController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
@ -58,13 +52,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
[ActionPermissionFilter(Permission = "system:notice:list")]
|
||||
public IActionResult QuerySysNotice([FromQuery] SysNoticeQueryDto parm)
|
||||
{
|
||||
var predicate = Expressionable.Create<SysNotice>();
|
||||
|
||||
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.NoticeTitle), m => m.NoticeTitle.Contains(parm.NoticeTitle));
|
||||
predicate = predicate.AndIF(parm.NoticeType != null, m => m.NoticeType == parm.NoticeType);
|
||||
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.CreateBy), m => m.Create_by.Contains(parm.CreateBy) || m.Update_by.Contains(parm.CreateBy));
|
||||
predicate = predicate.AndIF(parm.Status != null, m => m.Status == parm.Status);
|
||||
var response = _SysNoticeService.GetPages(predicate.ToExpression(), parm);
|
||||
PagedInfo<SysNotice> response = _SysNoticeService.GetPageList(parm);
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
@ -74,7 +62,6 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
/// <param name="NoticeId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{NoticeId}")]
|
||||
[ActionPermissionFilter(Permission = "system:notice:query")]
|
||||
public IActionResult GetSysNotice(int NoticeId)
|
||||
{
|
||||
var response = _SysNoticeService.GetFirst(x => x.NoticeId == NoticeId);
|
||||
@ -92,9 +79,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
public IActionResult AddSysNotice([FromBody] SysNoticeDto parm)
|
||||
{
|
||||
var modal = parm.Adapt<SysNotice>().ToCreate(HttpContext);
|
||||
modal.Create_by = HttpContext.GetName();
|
||||
modal.Create_time = DateTime.Now;
|
||||
|
||||
|
||||
int result = _SysNoticeService.Insert(modal, it => new
|
||||
{
|
||||
it.NoticeTitle,
|
||||
|
||||
@ -1,12 +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.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
@ -18,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;
|
||||
@ -71,8 +66,8 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
throw new CustomException($"修改岗位{post.PostName}失败,岗位编码已存在");
|
||||
}
|
||||
post.ToCreate(HttpContext);
|
||||
|
||||
post.Create_by = HttpContext.GetName();
|
||||
return ToResponse(PostService.Add(post));
|
||||
}
|
||||
|
||||
@ -94,7 +89,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
throw new CustomException($"修改岗位{post.PostName}失败,岗位编码已存在");
|
||||
}
|
||||
post.Update_by = HttpContext.GetName();
|
||||
post.ToUpdate(HttpContext);
|
||||
return ToResponse(PostService.Update(post));
|
||||
}
|
||||
|
||||
@ -126,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,10 +1,4 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
@ -17,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,21 +1,9 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Common;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Model.System.Dto;
|
||||
using Mapster;
|
||||
using ZR.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Aliyun.OSS;
|
||||
using MiniExcelLibs.OpenXml;
|
||||
using MiniExcelLibs;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
@ -24,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,11 +1,6 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
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;
|
||||
@ -19,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;
|
||||
@ -49,7 +45,7 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
{
|
||||
var list = UserService.SelectUserList(user, pager);
|
||||
|
||||
return SUCCESS(list, TIME_FORMAT_FULL);
|
||||
return SUCCESS(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -97,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>
|
||||
@ -147,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);
|
||||
@ -160,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);
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
@ -12,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;
|
||||
@ -45,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);
|
||||
@ -60,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,14 +1,7 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Extensions;
|
||||
using Mapster;
|
||||
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;
|
||||
using ZR.Model.System;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
@ -21,6 +14,7 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("system/Tasks")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class TasksController : BaseController
|
||||
{
|
||||
private ISysTasksQzService _tasksQzService;
|
||||
@ -40,19 +34,9 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
/// <returns></returns>
|
||||
[HttpGet("list")]
|
||||
[ActionPermissionFilter(Permission = "monitor:job:list")]
|
||||
public IActionResult ListTask([FromQuery] TasksQueryDto parm, [FromQuery] PagerInfo pager)
|
||||
public IActionResult ListTask([FromQuery] TasksQueryDto parm)
|
||||
{
|
||||
//开始拼装查询条件
|
||||
var predicate = Expressionable.Create<SysTasks>();
|
||||
|
||||
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.QueryText),
|
||||
m => m.Name.Contains(parm.QueryText) ||
|
||||
m.JobGroup.Contains(parm.QueryText) ||
|
||||
m.AssemblyName.Contains(parm.QueryText));
|
||||
predicate.AndIF(parm.TaskType != null, m => m.TaskType == parm.TaskType);
|
||||
|
||||
var response = _tasksQzService.GetPages(predicate.ToExpression(), pager);
|
||||
|
||||
var response = _tasksQzService.SelectTaskList(parm);
|
||||
return SUCCESS(response, TIME_FORMAT_FULL);
|
||||
}
|
||||
|
||||
@ -102,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();
|
||||
|
||||
@ -174,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);
|
||||
}
|
||||
@ -203,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);
|
||||
@ -234,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);
|
||||
@ -253,11 +237,12 @@ namespace ZR.Admin.WebApi.Controllers
|
||||
[Log(Title = "执行任务", BusinessType = BusinessType.OTHER)]
|
||||
public async Task<IActionResult> Run(string id)
|
||||
{
|
||||
if (!_tasksQzService.Any(m => m.ID == id))
|
||||
var result = await _tasksQzService.IsAnyAsync(m => m.ID == id);
|
||||
if (!result)
|
||||
{
|
||||
throw new CustomException("任务不存在");
|
||||
}
|
||||
var tasksQz = _tasksQzService.GetFirst(m => m.ID == id);
|
||||
var tasksQz = await _tasksQzService.GetFirstAsync(m => m.ID == id);
|
||||
var taskResult = await _schedulerServer.RunTaskScheduleAsync(tasksQz);
|
||||
|
||||
return ToResponse(taskResult);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,7 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
using ZR.Service.System.IService;
|
||||
@ -18,6 +13,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/monitor/logininfor")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysLogininforController : BaseController
|
||||
{
|
||||
private ISysLoginService sysLoginService;
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ZR.Admin.WebApi.Extensions;
|
||||
using ZR.Admin.WebApi.Filters;
|
||||
using ZR.Common;
|
||||
using ZR.Model.System.Dto;
|
||||
using ZR.Service.System.IService;
|
||||
|
||||
@ -15,6 +11,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("/monitor/operlog")]
|
||||
[ApiExplorerSettings(GroupName = "sys")]
|
||||
public class SysOperlogController : BaseController
|
||||
{
|
||||
private ISysOperLogService sysOperLogService;
|
||||
@ -69,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
ZR.Admin.WebApi/Controllers/WxOpenController.cs
Normal file
39
ZR.Admin.WebApi/Controllers/WxOpenController.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Web;
|
||||
|
||||
namespace ZR.Admin.WebApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信公众号
|
||||
/// </summary>
|
||||
[Route("[controller]/[action]")]
|
||||
[AllowAnonymous]
|
||||
public class WxOpenController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取签名
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
[Log(Title = "获取微信签名")]
|
||||
[HttpGet]
|
||||
public IActionResult GetSignature(string url = "")
|
||||
{
|
||||
url = HttpUtility.UrlDecode(url);
|
||||
var appId = AppSettings.App(new string[] { "WxOpen", "AppID" });
|
||||
var noncestr = Guid.NewGuid().ToString().Replace("-", "");
|
||||
var timestamp = DateTimeHelper.GetUnixTimeSeconds(DateTime.Now);
|
||||
var ticketResult = WxHelper.GetTicket();
|
||||
if (appId.IsEmpty()) return ToResponse(ResultCode.CUSTOM_ERROR, "appId未配置");
|
||||
if (ticketResult?.errcode != 0)
|
||||
{
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, "获取配置失败");
|
||||
}
|
||||
|
||||
var signature = WxHelper.GetSignature(ticketResult.ticket, timestamp.ToString(), noncestr, url);
|
||||
|
||||
return SUCCESS(new { appId, signature, noncestr, timestamp, url });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,268 +0,0 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using SqlSugar;
|
||||
using SqlSugar.IOC;
|
||||
using ZR.Admin.WebApi.Framework;
|
||||
using ZR.Model;
|
||||
using ZR.Model.System;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// sqlsugar 数据处理
|
||||
/// </summary>
|
||||
public static class DbExtension
|
||||
{
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
//全部数据权限
|
||||
public static long DATA_SCOPE_ALL = 1;
|
||||
//自定数据权限
|
||||
public static long DATA_SCOPE_CUSTOM = 2;
|
||||
//部门数据权限
|
||||
public static long DATA_SCOPE_DEPT = 3;
|
||||
//部门及以下数据权限
|
||||
public static long DATA_SCOPE_DEPT_AND_CHILD = 4;
|
||||
//仅本人数据权限
|
||||
public static long DATA_SCOPE_SELF = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化db
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="Configuration"></param>
|
||||
/// <param name="environment"></param>
|
||||
public static void AddDb(this IServiceCollection services, IConfiguration Configuration, IWebHostEnvironment environment)
|
||||
{
|
||||
List<DbConfigs> dbConfigs = Configuration.GetSection("DbConfigs").Get<List<DbConfigs>>();
|
||||
|
||||
var iocList = new List<IocConfig>();
|
||||
foreach (var item in dbConfigs.FindAll(f => !f.IsGenerateDb))
|
||||
{
|
||||
iocList.Add(new IocConfig()
|
||||
{
|
||||
ConfigId = item.ConfigId,
|
||||
ConnectionString = item.Conn,
|
||||
DbType = (IocDbType)item.DbType,
|
||||
IsAutoCloseConnection = item.IsAutoCloseConnection
|
||||
});
|
||||
}
|
||||
SugarIocServices.AddSqlSugar(iocList);
|
||||
ICacheService cache = new SqlSugarCache();
|
||||
SugarIocServices.ConfigurationSugar(db =>
|
||||
{
|
||||
var u = App.User;
|
||||
if (u != null)
|
||||
{
|
||||
FilterData(0);
|
||||
//ConfigId = 1的数据权限过滤
|
||||
//FilterData1(1);
|
||||
}
|
||||
|
||||
iocList.ForEach(iocConfig =>
|
||||
{
|
||||
SetSugarAop(db, iocConfig, cache);
|
||||
});
|
||||
});
|
||||
|
||||
if (Configuration["InitDb"].ParseToBool() == true && environment.IsDevelopment())
|
||||
{
|
||||
InitTable.InitDb();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据库Aop设置
|
||||
/// </summary>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="iocConfig"></param>
|
||||
/// <param name="cache"></param>
|
||||
private static void SetSugarAop(SqlSugarClient db, IocConfig iocConfig, ICacheService cache)
|
||||
{
|
||||
var config = db.GetConnectionScope(iocConfig.ConfigId).CurrentConnectionConfig;
|
||||
|
||||
string configId = config.ConfigId;
|
||||
db.GetConnectionScope(configId).Aop.OnLogExecuting = (sql, pars) =>
|
||||
{
|
||||
string log = $"【db{configId} SQL语句】{UtilMethods.GetSqlString(config.DbType, sql, pars)}\n";
|
||||
if (sql.TrimStart().StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.Info(log);
|
||||
}
|
||||
else if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.Warn(log);
|
||||
}
|
||||
else if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("TRUNCATE", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.Error(log);
|
||||
}
|
||||
else
|
||||
{
|
||||
log = $"【db{configId} SQL语句】dbo.{sql} {string.Join(", ", pars.Select(x => x.ParameterName + " = " + GetParsValue(x)))};\n";
|
||||
logger.Info(log);
|
||||
}
|
||||
};
|
||||
db.GetConnectionScope(configId).Aop.OnError = (ex) =>
|
||||
{
|
||||
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
|
||||
|
||||
string sql = "【错误SQL】" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n";
|
||||
logger.Error(ex, $"{sql}\r\n{ex.Message}\r\n{ex.StackTrace}");
|
||||
};
|
||||
db.GetConnectionScope(configId).Aop.DataExecuting = (oldValue, entiyInfo) =>
|
||||
{
|
||||
};
|
||||
|
||||
db.GetConnectionScope(configId).CurrentConnectionConfig.MoreSettings = new ConnMoreSettings()
|
||||
{
|
||||
IsAutoRemoveDataCache = true
|
||||
};
|
||||
db.GetConnectionScope(configId).CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices()
|
||||
{
|
||||
DataInfoCacheService = cache,
|
||||
EntityService = (c, p) =>
|
||||
{
|
||||
if (p.IsPrimarykey == true)//主键不能为null
|
||||
{
|
||||
p.IsNullable = false;
|
||||
}
|
||||
else if (p.ExtendedAttribute?.ToString() == ProteryConstant.NOTNULL.ToString())
|
||||
{
|
||||
p.IsNullable = false;
|
||||
}
|
||||
else//则否默认为null
|
||||
{
|
||||
p.IsNullable = true;
|
||||
}
|
||||
|
||||
if (config.DbType == DbType.PostgreSQL)
|
||||
{
|
||||
if (c.Name == nameof(SysMenu.IsCache) || c.Name == nameof(SysMenu.IsFrame))
|
||||
{
|
||||
p.DataType = "char(1)";
|
||||
}
|
||||
}
|
||||
#region 兼容Oracle
|
||||
if (config.DbType == DbType.Oracle)
|
||||
{
|
||||
if (p.IsIdentity == true)
|
||||
{
|
||||
if (p.EntityName == nameof(SysUser))
|
||||
{
|
||||
p.OracleSequenceName = "SEQ_SYS_USER_USERID";
|
||||
}
|
||||
else if (p.EntityName == nameof(SysRole))
|
||||
{
|
||||
p.OracleSequenceName = "SEQ_SYS_ROLE_ROLEID";
|
||||
}
|
||||
else if (p.EntityName == nameof(SysDept))
|
||||
{
|
||||
p.OracleSequenceName = "SEQ_SYS_DEPT_DEPTID";
|
||||
}
|
||||
else if (p.EntityName == nameof(SysMenu))
|
||||
{
|
||||
p.OracleSequenceName = "SEQ_SYS_MENU_MENUID";
|
||||
}
|
||||
else
|
||||
{
|
||||
p.OracleSequenceName = "SEQ_ID";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static object GetParsValue(SugarParameter x)
|
||||
{
|
||||
if (x.DbType == System.Data.DbType.String || x.DbType == System.Data.DbType.DateTime || x.DbType == System.Data.DbType.String)
|
||||
{
|
||||
return "'" + x.Value + "'";
|
||||
}
|
||||
return x.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据过滤
|
||||
/// </summary>
|
||||
/// <param name="configId">多库id</param>
|
||||
private static void FilterData(int configId)
|
||||
{
|
||||
//获取当前用户的信息
|
||||
var user = JwtUtil.GetLoginUser(App.HttpContext);
|
||||
if (user == null) return;
|
||||
//管理员不过滤
|
||||
if (user.RoleIds.Any(f => f.Equals(GlobalConstant.AdminRole))) return;
|
||||
var db = DbScoped.SugarScope.GetConnectionScope(configId);
|
||||
var expUser = Expressionable.Create<SysUser>().Or(it => 1 == 1);
|
||||
var expRole = Expressionable.Create<SysRole>().Or(it => 1 == 1);
|
||||
var expLoginlog = Expressionable.Create<SysLogininfor>();
|
||||
|
||||
foreach (var role in user.Roles.OrderBy(f => f.DataScope))
|
||||
{
|
||||
long dataScope = role.DataScope;
|
||||
if (DATA_SCOPE_ALL.Equals(dataScope))//所有权限
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (DATA_SCOPE_CUSTOM.Equals(dataScope))//自定数据权限
|
||||
{
|
||||
//" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
|
||||
|
||||
expUser.Or(it => SqlFunc.Subqueryable<SysRoleDept>().Where(f => f.DeptId == it.DeptId && f.RoleId == role.RoleId).Any());
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT.Equals(dataScope))//本部门数据
|
||||
{
|
||||
expUser.Or(it => it.DeptId == user.DeptId);
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT_AND_CHILD.Equals(dataScope))//本部门及以下数据
|
||||
{
|
||||
//SQl OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )
|
||||
var allChildDepts = db.Queryable<SysDept>().ToChildList(it => it.ParentId, user.DeptId);
|
||||
|
||||
expUser.Or(it => allChildDepts.Select(f => f.DeptId).ToList().Contains(it.DeptId));
|
||||
}
|
||||
else if (DATA_SCOPE_SELF.Equals(dataScope))//仅本人数据
|
||||
{
|
||||
expUser.Or(it => it.UserId == user.UserId);
|
||||
expRole.Or(it => user.RoleIds.Contains(it.RoleKey));
|
||||
expLoginlog.And(it => it.UserName == user.UserName);
|
||||
}
|
||||
db.QueryFilter.AddTableFilter(expUser.ToExpression());
|
||||
db.QueryFilter.AddTableFilter(expRole.ToExpression());
|
||||
db.QueryFilter.AddTableFilter(expLoginlog.ToExpression());
|
||||
}
|
||||
}
|
||||
|
||||
private static void FilterData1(int configId)
|
||||
{
|
||||
//获取当前用户的信息
|
||||
var user = JwtUtil.GetLoginUser(App.HttpContext);
|
||||
if (user == null) return;
|
||||
var db = DbScoped.SugarScope.GetConnectionScope(configId);
|
||||
|
||||
foreach (var role in user.Roles.OrderBy(f => f.DataScope))
|
||||
{
|
||||
long dataScope = role.DataScope;
|
||||
if (DATA_SCOPE_ALL.Equals(dataScope))//所有权限
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (DATA_SCOPE_CUSTOM.Equals(dataScope))//自定数据权限
|
||||
{
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT.Equals(dataScope))//本部门数据
|
||||
{
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT_AND_CHILD.Equals(dataScope))//本部门及以下数据
|
||||
{
|
||||
|
||||
}
|
||||
else if (DATA_SCOPE_SELF.Equals(dataScope))//仅本人数据
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
{
|
||||
public static class EntityExtension
|
||||
{
|
||||
public static TSource ToCreate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null) return source;
|
||||
|
||||
types.GetProperty("CreateTime")?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("AddTime")?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("UpdateTime")?.SetValue(source, DateTime.Now, null);
|
||||
if (types.GetProperty("Create_by") != null && context != null)
|
||||
{
|
||||
types.GetProperty("Create_by")?.SetValue(source, context.GetName(), null);
|
||||
}
|
||||
if (types.GetProperty("Create_By") != null && context != null)
|
||||
{
|
||||
types.GetProperty("Create_By")?.SetValue(source, context.GetName(), null);
|
||||
}
|
||||
if (types.GetProperty("CreateBy") != null && context != null)
|
||||
{
|
||||
types.GetProperty("CreateBy")?.SetValue(source, context.GetName(), null);
|
||||
}
|
||||
if (types.GetProperty("UserId") != null && context != null)
|
||||
{
|
||||
types.GetProperty("UserId")?.SetValue(source, context.GetUId(), null);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
public static TSource ToUpdate<TSource>(this TSource source, HttpContext? context = null)
|
||||
{
|
||||
var types = source?.GetType();
|
||||
if (types == null) return source;
|
||||
|
||||
types.GetProperty("UpdateTime")?.SetValue(source, DateTime.Now, null);
|
||||
types.GetProperty("Update_time")?.SetValue(source, DateTime.Now, null);
|
||||
|
||||
types.GetProperty("UpdateBy")?.SetValue(source,context.GetName(), null);
|
||||
types.GetProperty("Update_by")?.SetValue(source, context.GetName(), null);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
using JinianNet.JNTemplate;
|
||||
using ZR.Common;
|
||||
|
||||
namespace ZR.Admin.WebApi.Extensions
|
||||
{
|
||||
public static class LogoExtension
|
||||
{
|
||||
public static void AddLogo(this IServiceCollection services)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
var contentTpl = JnHelper.ReadTemplate("", "logo.txt");
|
||||
var content = contentTpl?.Render();
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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}成功");
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZR.Admin.WebApi.Framework
|
||||
{
|
||||
public class CookieUtil
|
||||
{
|
||||
public static void WhiteCookie(HttpContext context, List<Claim> claims)
|
||||
{
|
||||
//2.创建声明主题 指定认证方式 这里使用cookie
|
||||
var claimsIdentity = new ClaimsIdentity(claims, "Login");
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await context.SignInAsync(
|
||||
JwtBearerDefaults.AuthenticationScheme,//这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。
|
||||
new ClaimsPrincipal(claimsIdentity),
|
||||
new AuthenticationProperties()
|
||||
{
|
||||
IsPersistent = true,
|
||||
AllowRefresh = true,
|
||||
ExpiresUtc = DateTimeOffset.Now.AddDays(1),//有效时间
|
||||
});
|
||||
}).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
ZR.Admin.WebApi/GlobalUsing.cs
Normal file
10
ZR.Admin.WebApi/GlobalUsing.cs
Normal file
@ -0,0 +1,10 @@
|
||||
global using ZR.Common;
|
||||
global using Microsoft.AspNetCore.Authorization;
|
||||
global using Infrastructure;
|
||||
global using Infrastructure.Attribute;
|
||||
global using Infrastructure.Enums;
|
||||
global using Infrastructure.Model;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
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();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
@ -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,31 +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;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
//InternalApp.InternalServices = builder.Services;
|
||||
builder.Services.AddJwt();
|
||||
//配置文件
|
||||
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
|
||||
//app服务注册
|
||||
builder.Services.AddAppService();
|
||||
//开启计划任务
|
||||
builder.Services.AddTaskSchedulers();
|
||||
@ -81,23 +60,43 @@ builder.Services.AddMvc(options =>
|
||||
})
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
//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();
|
||||
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>();
|
||||
|
||||
//使可以多次多去body内容
|
||||
//请求头转发
|
||||
//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内容
|
||||
context.Request.EnableBuffering();
|
||||
if (context.Request.Query.TryGetValue("access_token", out var token))
|
||||
{
|
||||
@ -117,8 +116,11 @@ app.UseAuthorization();
|
||||
|
||||
//开启缓存
|
||||
app.UseResponseCaching();
|
||||
//恢复/启动任务
|
||||
app.UseAddTaskSchedulers();
|
||||
if (builder.Environment.IsProduction())
|
||||
{
|
||||
//恢复/启动任务
|
||||
app.UseAddTaskSchedulers();
|
||||
}
|
||||
//使用swagger
|
||||
app.UseSwagger();
|
||||
//启用客户端IP限制速率
|
||||
@ -132,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,21 +15,15 @@
|
||||
<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.5" />
|
||||
<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.1.4" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.2.3" />
|
||||
<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>
|
||||
<Folder Include="Controllers\" />
|
||||
<Folder Include="Properties\PublishProfiles\" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -37,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>
|
||||
|
||||
@ -12,32 +12,35 @@
|
||||
"DbType": 0, //数据库类型 MySql = 0, SqlServer = 1, Oracle = 3,PgSql = 4
|
||||
"ConfigId": "0", //多租户唯一标识
|
||||
"IsAutoCloseConnection": true
|
||||
},
|
||||
{
|
||||
//代码生成连接字符串,注意{dbName}为固定格式,不要填写数据库名
|
||||
"Conn": "Data Source=LAPTOP-STKF2M8H\\SQLEXPRESS;User ID=admin;Password=admin123;Initial Catalog={dbName};",
|
||||
"DbType": 1,
|
||||
"ConfigId": "0",
|
||||
"IsAutoCloseConnection": true,
|
||||
"DbName": "ZrAdmin", //代码生成默认连接数据库
|
||||
"IsGenerateDb": true //是否代码生成使用库,不要改动
|
||||
}
|
||||
//...下面添加更多的数据库源
|
||||
],
|
||||
//代码生成数据库配置
|
||||
"CodeGenDbConfig": {
|
||||
//代码生成连接字符串,注意{dbName}为固定格式,不要填写数据库名
|
||||
"Conn": "Data Source=LAPTOP-STKF2M8H\\SQLEXPRESS;User ID=admin;Password=admin123;Initial Catalog={dbName};",
|
||||
"DbType": 1,
|
||||
"IsAutoCloseConnection": true,
|
||||
"DbName": "ZrAdmin" //代码生成默认连接数据库,Oracle库是实例的名称
|
||||
},
|
||||
"urls": "http://localhost:8888", //项目启动url,如果改动端口前端对应devServer也需要进行修改
|
||||
"corsUrls": "http://localhost:8887", //跨域地址(前端启动项目,前后端分离单独部署需要设置),多个用","隔开
|
||||
"corsUrls": [ "http://localhost:8887", "http://localhost:8886" ], //跨域地址(前端启动项目,前后端分离单独部署需要设置),多个用","隔开
|
||||
"JwtSettings": {
|
||||
"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": "uploads", //本地上传默认文件存储目录 wwwroot/uploads, 如果saveType= 2 (请使用完整路径,比如 /home/resource)
|
||||
"localSavePath": "", //本地上传默认文件存储目录 wwwroot
|
||||
"maxSize": 15, //上传文件大小限制 15M
|
||||
"notAllowedExt": [ ".bat", ".exe", ".jar", ".js" ]
|
||||
},
|
||||
@ -57,12 +60,30 @@
|
||||
"CorpSecret": "",
|
||||
"SendUser": "@all"
|
||||
},
|
||||
//微信公众号设置
|
||||
"WxOpen": {
|
||||
"AppID": "",
|
||||
"AppSecret": ""
|
||||
},
|
||||
//代码生成配置
|
||||
"gen": {
|
||||
"autoPre": true, //自动去除表前缀
|
||||
//是否显示移动端代码生成
|
||||
"showApp": false,
|
||||
//自动去除表前缀
|
||||
"autoPre": true,
|
||||
"author": "admin",
|
||||
"tablePrefix": "sys_", //"表前缀(生成类名不会包含表前缀,多个用逗号分隔)",
|
||||
"vuePath": "" //前端代码存储路径eg:D:\Work\ZRAdmin-Vue3
|
||||
"vuePath": "", //前端代码存储路径eg:D:\Work\ZRAdmin-Vue3
|
||||
"csharpTypeArr": {
|
||||
"string": [ "varchar", "nvarchar", "text", "longtext" ],
|
||||
"int": [ "int", "integer", "smallint", "int4", "int8", "int2" ],
|
||||
"long": [ "bigint", "number" ],
|
||||
"float": [ "numeric", "real", "float" ],
|
||||
"decimal": [ "money", "decimal", "smallmoney" ],
|
||||
"dateTime": [ "date", "datetime", "datetime2", "smalldatetime", "timestamp" ],
|
||||
"byte": [ "tinyint" ],
|
||||
"bool": [ "bit" ]
|
||||
}
|
||||
},
|
||||
//邮箱配置信息
|
||||
"MailOptions": {
|
||||
@ -71,11 +92,12 @@
|
||||
//发送人邮箱
|
||||
"FromEmail": "", //eg:xxxx@qq.com
|
||||
//发送人邮箱密码
|
||||
"Password": "123456",
|
||||
"Password": "",
|
||||
//协议
|
||||
"Smtp": "smtp.qq.com",
|
||||
"Port": 587,
|
||||
"Signature": "系统邮件,请勿回复!"
|
||||
"Signature": "系统邮件,请勿回复!",
|
||||
"UseSsl": true
|
||||
},
|
||||
//redis服务配置
|
||||
"RedisServer": {
|
||||
@ -90,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",
|
||||
@ -109,12 +131,7 @@
|
||||
"Period": "3s",
|
||||
"Limit": 1
|
||||
}
|
||||
],
|
||||
"IpRateLimitPolicies": {
|
||||
//ip规则
|
||||
"IpRules": [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
//验证码配置
|
||||
"CaptchaOptions": {
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Enums;
|
||||
using Infrastructure.Model;
|
||||
using Mapster;
|
||||
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;
|
||||
using ${options.BaseNamespace}Common;
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
using MiniExcelLibs;
|
||||
$end
|
||||
|
||||
//创建时间:${replaceDto.AddTime}
|
||||
namespace ${options.ApiControllerNamespace}.Controllers
|
||||
@ -68,7 +64,7 @@ $end
|
||||
[ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:query")]
|
||||
public IActionResult Get${replaceDto.ModelTypeName}(${replaceDto.PKType} ${replaceDto.PKName})
|
||||
{
|
||||
var response = _${replaceDto.ModelTypeName}Service.GetFirst(x => x.${replaceDto.PKName} == ${replaceDto.PKName});
|
||||
var response = _${replaceDto.ModelTypeName}Service.GetInfo(${replaceDto.PKName});
|
||||
|
||||
var info = response.Adapt<${replaceDto.ModelTypeName}>();
|
||||
return SUCCESS(info);
|
||||
@ -88,7 +84,7 @@ $if(replaceDto.ShowBtnAdd)
|
||||
|
||||
var response = _${replaceDto.ModelTypeName}Service.Add${replaceDto.ModelTypeName}(modal);
|
||||
|
||||
return ToResponse(response);
|
||||
return SUCCESS(response);
|
||||
}
|
||||
$end
|
||||
|
||||
@ -168,6 +164,40 @@ $if(replaceDto.ShowBtnTruncate)
|
||||
}
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
/// <summary>
|
||||
/// 导入
|
||||
/// </summary>
|
||||
/// <param name="formFile"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("importData")]
|
||||
[Log(Title = "${genTable.FunctionName}导入", BusinessType = BusinessType.IMPORT, IsSaveRequestData = false)]
|
||||
[ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:import")]
|
||||
public IActionResult ImportData([FromForm(Name = "file")] IFormFile formFile)
|
||||
{
|
||||
List<${replaceDto.ModelTypeName}Dto> list = new();
|
||||
using (var stream = formFile.OpenReadStream())
|
||||
{
|
||||
list = stream.Query<${replaceDto.ModelTypeName}Dto>(startCell: "A1").ToList();
|
||||
}
|
||||
|
||||
return SUCCESS(_${replaceDto.ModelTypeName}Service.Import${replaceDto.ModelTypeName}(list.Adapt<List<${replaceDto.ModelTypeName}>>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ${genTable.FunctionName}导入模板下载
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("importTemplate")]
|
||||
[Log(Title = "${genTable.FunctionName}模板", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ImportTemplateExcel()
|
||||
{
|
||||
var result = DownloadImportTemplate(new List<${replaceDto.ModelTypeName}Dto>() { }, "${replaceDto.ModelTypeName}");
|
||||
return ExportExcel(result.Item2, result.Item1);
|
||||
}
|
||||
$end
|
||||
|
||||
$if(showCustomInput)
|
||||
/// <summary>
|
||||
/// 保存排序
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
//using ${options.ModelsNamespace}.${options.SubNamespace};
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
using MiniExcelLibs.Attributes;
|
||||
$end
|
||||
@ -42,6 +39,7 @@ $end
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
$if(item.IsExport)
|
||||
[ExcelColumn(Name = "$if(item.ColumnComment == "")${item.CsharpField}${else}${item.ColumnComment}${end}"$if(item.CsharpType == "DateTime"), Format = "yyyy-MM-dd HH:mm:ss"$end)]
|
||||
[ExcelColumnName("$if(item.ColumnComment == "")${item.CsharpField}${else}${item.ColumnComment}${end}")]
|
||||
$else
|
||||
[ExcelIgnore]
|
||||
$end
|
||||
@ -57,14 +55,14 @@ $if(genTable.TplCategory == "subNav" && genTable.SubTable != null)
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
[ExcelIgnore]
|
||||
$end
|
||||
public ${genTable.SubTable.ClassName} ${genTable.SubTable.ClassName}Nav { get; set; }
|
||||
public ${genTable.SubTable.ClassName}Dto ${genTable.SubTable.ClassName}Nav { get; set; }
|
||||
$end
|
||||
|
||||
$if(genTable.TplCategory == "subNavMore" && genTable.SubTable != null)
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
[ExcelIgnore]
|
||||
$end
|
||||
public List<${genTable.SubTable.ClassName}> ${genTable.SubTable.ClassName}Nav { get; set; }
|
||||
public List<${genTable.SubTable.ClassName}Dto> ${genTable.SubTable.ClassName}Nav { get; set; }
|
||||
$end
|
||||
}
|
||||
}
|
||||
@ -13,14 +13,20 @@ namespace ${options.IServicsNamespace}.${options.SubNamespace}.I${options.SubNam
|
||||
{
|
||||
PagedInfo<${replaceDto.ModelTypeName}Dto> GetList(${replaceDto.ModelTypeName}QueryDto parm);
|
||||
|
||||
${replaceDto.ModelTypeName} GetInfo(${replaceDto.PKType} ${replaceDto.PKName});
|
||||
|
||||
$if(genTable.TplCategory == "tree")
|
||||
List<${replaceDto.ModelTypeName}> GetTreeList(${replaceDto.ModelTypeName}QueryDto parm);
|
||||
$end
|
||||
int Add${replaceDto.ModelTypeName}(${replaceDto.ModelTypeName} parm);
|
||||
${replaceDto.ModelTypeName} Add${replaceDto.ModelTypeName}(${replaceDto.ModelTypeName} parm);
|
||||
|
||||
int Update${replaceDto.ModelTypeName}(${replaceDto.ModelTypeName} parm);
|
||||
$if(replaceDto.ShowBtnTruncate)
|
||||
bool Truncate${replaceDto.ModelTypeName}();
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
(string, object, object) Import${replaceDto.ModelTypeName}(List<${replaceDto.ModelTypeName}> list);
|
||||
$end
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using SqlSugar;
|
||||
using System.Collections.Generic;
|
||||
$if(genTable.TplCategory.Contains("subNav") && genTable.SubTable != null)
|
||||
$if(genTable.TplCategory.Contains("subNav") && genTable.SubTable != null)
|
||||
using ${subTableOptions.ModelsNamespace}.${subTableOptions.SubNamespace};
|
||||
$end
|
||||
|
||||
@ -37,7 +34,7 @@ $if(genTable.TplCategory == "tree")
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public List<${replaceDto.ModelTypeName}> Children { get; set; }
|
||||
$end
|
||||
$if(genTable.TplCategory == "subNav" && genTable.SubTable != null)
|
||||
$if((genTable.TplCategory == "subNav" || genTable.TplCategory == "sub") && genTable.SubTable != null)
|
||||
[Navigate(NavigateType.OneToOne, nameof(${replaceDto.PKName}))] //自定义关系映射
|
||||
public ${genTable.SubTable.ClassName} ${genTable.SubTable.ClassName}Nav { get; set; }
|
||||
$end
|
||||
|
||||
@ -51,7 +51,7 @@ $end
|
||||
$end
|
||||
var response = Queryable()
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName)
|
||||
.Includes(x => x.${genTable.SubTable.ClassName}Nav) //填充子对象
|
||||
//.Includes(x => x.${genTable.SubTable.ClassName}Nav) //填充子对象
|
||||
$end
|
||||
$if(genTable.Options.SortField != "" && genTable.Options.SortField != null)
|
||||
//.OrderBy("${genTable.Options.SortField} ${genTable.Options.SortType}")
|
||||
@ -90,14 +90,35 @@ $end
|
||||
}
|
||||
$end
|
||||
|
||||
/// <summary>
|
||||
/// 获取详情
|
||||
/// </summary>
|
||||
/// <param name="${replaceDto.PKName}"></param>
|
||||
/// <returns></returns>
|
||||
public ${replaceDto.ModelTypeName} GetInfo(${replaceDto.PKType} ${replaceDto.PKName})
|
||||
{
|
||||
var response = Queryable()
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName)
|
||||
.Includes(x => x.${genTable.SubTable.ClassName}Nav) //填充子对象
|
||||
$end
|
||||
.Where(x => x.${replaceDto.PKName} == ${replaceDto.PKName})
|
||||
.First();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加${genTable.FunctionName}
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public int Add${replaceDto.ModelTypeName}(${replaceDto.ModelTypeName} model)
|
||||
public ${replaceDto.ModelTypeName} Add${replaceDto.ModelTypeName}(${replaceDto.ModelTypeName} model)
|
||||
{
|
||||
return Add(model, true);
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName)
|
||||
return Context.InsertNav(model).Include(s1 => s1.${genTable.SubTable.ClassName}Nav).ExecuteReturnEntity();
|
||||
$else
|
||||
return Context.Insertable(model).ExecuteReturnEntity();
|
||||
$end
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -116,7 +137,11 @@ $end
|
||||
${end}
|
||||
//});
|
||||
//return response;
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName)
|
||||
return Context.UpdateNav(model).Include(z1 => z1.${genTable.SubTable.ClassName}Nav).ExecuteCommand() ? 1 : 0;
|
||||
$else
|
||||
return Update(model, true);
|
||||
$end
|
||||
}
|
||||
$if(replaceDto.ShowBtnTruncate)
|
||||
/// <summary>
|
||||
@ -134,5 +159,40 @@ $if(replaceDto.ShowBtnTruncate)
|
||||
return Truncate();
|
||||
}
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
/// <summary>
|
||||
/// 导入${genTable.FunctionName}
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (string, object, object) Import${replaceDto.ModelTypeName}(List<${replaceDto.ModelTypeName}> list)
|
||||
{
|
||||
var x = Context.Storageable(list)
|
||||
.SplitInsert(it => !it.Any())
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.IsRequired && column.IsIncrement == false)
|
||||
.SplitError(x => x.Item.${column.CsharpField}.IsEmpty(), "${column.ColumnComment}不能为空")
|
||||
$end
|
||||
$end
|
||||
//.WhereColumns(it => it.UserName)//如果不是主键可以这样实现(多字段it=>new{it.x1,it.x2})
|
||||
.ToStorage();
|
||||
var result = x.AsInsertable.ExecuteCommand();//插入可插入部分;
|
||||
|
||||
string msg = $"插入{x.InsertList.Count} 更新{x.UpdateList.Count} 错误数据{x.ErrorList.Count} 不计算数据{x.IgnoreList.Count} 删除数据{x.DeleteList.Count} 总共{x.TotalList.Count}";
|
||||
Console.WriteLine(msg);
|
||||
|
||||
//输出错误信息
|
||||
foreach (var item in x.ErrorList)
|
||||
{
|
||||
Console.WriteLine("错误" + item.StorageMessage);
|
||||
}
|
||||
foreach (var item in x.IgnoreList)
|
||||
{
|
||||
Console.WriteLine("忽略" + item.StorageMessage);
|
||||
}
|
||||
|
||||
return (msg, x.ErrorList, x.IgnoreList);
|
||||
}
|
||||
$end
|
||||
}
|
||||
}
|
||||
78
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/api.txt
Normal file
78
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/api.txt
Normal file
@ -0,0 +1,78 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* ${genTable.functionName}分页查询
|
||||
* @param {查询条件} data
|
||||
*/
|
||||
export function list${genTable.BusinessName}(query) {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}/list',
|
||||
method: 'get',
|
||||
data: query,
|
||||
})
|
||||
}
|
||||
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
/**
|
||||
* 新增${genTable.functionName}
|
||||
* @param data
|
||||
*/
|
||||
export function add${genTable.BusinessName}(data) {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}',
|
||||
method: 'post',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
/**
|
||||
* 修改${genTable.functionName}
|
||||
* @param data
|
||||
*/
|
||||
export function update${genTable.BusinessName}(data) {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}',
|
||||
method: 'PUT',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
$end
|
||||
/**
|
||||
* 获取${genTable.functionName}详情
|
||||
* @param {Id}
|
||||
*/
|
||||
export function get${genTable.BusinessName}(id) {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
$if(replaceDto.ShowBtnDelete || replaceDto.ShowBtnMultiDel)
|
||||
/**
|
||||
* 删除${genTable.functionName}
|
||||
* @param {主键} pid
|
||||
*/
|
||||
export function del${genTable.BusinessName}(pid) {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}/' + pid,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
$end
|
||||
$if(replaceDto.ShowBtnTruncate)
|
||||
// 清空${genTable.functionName}
|
||||
export function clear${genTable.BusinessName}() {
|
||||
return request({
|
||||
url: '/${genTable.ModuleName}/${genTable.BusinessName}/clean',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
$end
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
// 导出${genTable.functionName}
|
||||
export async function export${genTable.BusinessName}(query) {
|
||||
await downFile('$/{genTable.ModuleName}/${genTable.BusinessName}/export', { ...query })
|
||||
}
|
||||
$end
|
||||
210
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/form.txt
Normal file
210
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/form.txt
Normal file
@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<view class="edit-form">
|
||||
<u--form labelPosition="left" :model="form" labelWidth="90px" :rules="rules" ref="uForm">
|
||||
$foreach(column in genTable.Columns)
|
||||
$set(columnName = column.CsharpFieldFl)
|
||||
$set(value = "item.value")
|
||||
$set(number = "")
|
||||
$set(labelName = column.ColumnComment)
|
||||
$if(column.CsharpType == "int" || column.CsharpType == "long")
|
||||
$set(value = "parseInt(item.value)")
|
||||
$set(number = ".number")
|
||||
$end
|
||||
|
||||
$if(column.IsPK || column.IsIncrement)
|
||||
$if(column.IsPK && column.IsIncrement == false)
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<u--input type="number" v-model.number="form.${columnName}" placeholder="请输入${labelName}" :disabled="opertype != 1"></u--input>
|
||||
</u-form-item>
|
||||
$else
|
||||
<u-form-item label="${labelName}" prop="${columnName}" v-if="opertype != 1">
|
||||
<u--input type="number" v-model.number="form.${columnName}" placeholder="请输入${labelName}" :disabled="true"/>
|
||||
</u-form-item>
|
||||
$end
|
||||
$else
|
||||
$if(column.HtmlType == "radio" || column.HtmlType == "selectRadio")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<u-radio-group v-model="form.${columnName}">
|
||||
<u-radio v-for="item in ${if(column.DictType != "")}dict.type.${column.DictType}${else}${column.CsharpFieldFl}Options$end" :name="${value}" class="margin-right-xl">{{item.label}}</u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "checkbox")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<view class="">
|
||||
<u-checkbox-group v-model="form.${columnName}Checked">
|
||||
<u-checkbox :customStyle="{marginRight: '20px', marginBottom: '15px'}" v-for="(item, index) in ${if(column.DictType != "")}dict.type.${column.DictType}${else}${column.CsharpFieldFl}Options$end" :key="index"
|
||||
:label="item.label" :name="${value}">
|
||||
</u-checkbox>
|
||||
</u-checkbox-group>
|
||||
</view>
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "inputNumber" || column.HtmlType == "customInput")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<u-number-box v-model="form.${columnName}"></u-number-box>
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "datetime" || column.HtmlType == "month")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<uni-datetime-picker v-model="form.${columnName}" />
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "textarea")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<u--textarea v-model="form.${columnName}" placeholder="请输入内容" count ></u--textarea>
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "imageUpload" || column.HtmlType == "fileUpload")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<uploadImage v-model="form.${columnName}"></uploadImage>
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "select" || column.HtmlType == "selectMulti")
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<uni-data-select v-model="form.${columnName}" :clear="true" :localdata="${if(column.DictType != "")}dict.type.${column.DictType}${else}${column.CsharpFieldFl}Options$end"
|
||||
format="{label} - {value}"></uni-data-select>
|
||||
</u-form-item>
|
||||
$else
|
||||
<u-form-item label="${labelName}" prop="${columnName}">
|
||||
<u--input v-model${number}="form.${columnName}" placeholder="请输入${labelName}" ${column.DisabledStr}/>
|
||||
</u-form-item>
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
|
||||
</u--form>
|
||||
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "@/static/scss/page.scss";
|
||||
import {
|
||||
get${genTable.BusinessName},
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
add${genTable.BusinessName},
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
update${genTable.BusinessName},
|
||||
$end
|
||||
}
|
||||
from '@/api/${tool.FirstLowerCase(genTable.ModuleName)}/${genTable.BusinessName.ToLower()}.js'
|
||||
|
||||
export default {
|
||||
$if(replaceDto.UploadFile == 1)
|
||||
components: {
|
||||
UploadImage
|
||||
},
|
||||
$end
|
||||
dicts: [
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "radio" || item.HtmlType.Contains("select") || item.HtmlType == "checkbox") && item.DictType != "")
|
||||
"${item.DictType}",
|
||||
$end
|
||||
$end
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
rules: {
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.IsRequired && column.IsIncrement == false)
|
||||
${column.CsharpFieldFl}: [{
|
||||
required: true,
|
||||
message: "${column.ColumnComment}不能为空",
|
||||
trigger: [ 'change', 'blur' ],
|
||||
$if(column.CsharpType == "int" || column.CsharpType == "long") type: "number"$end
|
||||
}],
|
||||
$end
|
||||
$end
|
||||
},
|
||||
opertype: 0,
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "radio" || item.HtmlType == "select" || item.HtmlType == "checkbox") && item.DictType == "")
|
||||
// ${item.ColumnComment}选项列表 格式 eg:{ label: '标签', value: '0'}
|
||||
${item.CsharpFieldFl}Options: [],
|
||||
$end
|
||||
$end
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
// 需要在onReady中设置规则
|
||||
setTimeout(() => {
|
||||
this.${refs}refs.uForm.setRules(this.rules)
|
||||
}, 300)
|
||||
},
|
||||
onLoad(e) {
|
||||
this.opertype = e.opertype
|
||||
if (e.id) {
|
||||
get${genTable.BusinessName}(e.id).then(res => {
|
||||
const {
|
||||
code,
|
||||
data
|
||||
} = res
|
||||
if (code == 200) {
|
||||
this.form = {
|
||||
...data,
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.HtmlType == "checkbox")
|
||||
${item.CsharpFieldFl}Checked: data.${item.CsharpFieldFl} ? data.${item.CsharpFieldFl}.split(',') : [],
|
||||
$end
|
||||
$end
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.reset()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
reset(){
|
||||
this.form = {
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "checkbox"))
|
||||
${item.CsharpFieldFl}Checked: [],
|
||||
$else
|
||||
$item.CsharpFieldFl: undefined,
|
||||
$end
|
||||
$end
|
||||
};
|
||||
},
|
||||
submit() {
|
||||
this.${refs}refs.uForm.validate().then(res => {
|
||||
this.${modal}modal.msg('表单校验通过')
|
||||
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.HtmlType == "checkbox")
|
||||
this.form.${item.CsharpFieldFl} = this.form.${item.CsharpFieldFl}Checked.toString();
|
||||
$end
|
||||
$end
|
||||
if (this.form.${replaceDto.FistLowerPk} != undefined && this.opertype == 2) {
|
||||
update${genTable.BusinessName}(this.form).then((res) => {
|
||||
this.${modal}modal.msgSuccess("修改成功")
|
||||
})
|
||||
} else {
|
||||
add${genTable.BusinessName}(this.form).then((res) => {
|
||||
this.${modal}modal.msgSuccess("新增成功")
|
||||
})
|
||||
}
|
||||
}).catch(errors => {
|
||||
this.${modal}modal.msg('表单校验失败')
|
||||
})
|
||||
},
|
||||
handleCancel() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.btn-wrap {
|
||||
margin: 150rpx auto 0 auto;
|
||||
width: 80%
|
||||
}
|
||||
</style>
|
||||
288
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/vue2.txt
Normal file
288
ZR.Admin.WebApi/wwwroot/CodeGenTemplate/app/vue2.txt
Normal file
@ -0,0 +1,288 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="search-bar">
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
<u-button type="primary" size="small" shape="circle" icon="plus" v-if="checkPermi(['${replaceDto.PermissionPrefix}:add'])"
|
||||
@click="handleAdd" :customStyle="{'width': '80px', 'margin': '10px'}">新增</u-button>
|
||||
$end
|
||||
<u-search :disabled="true" placeholder="请输入要搜索的内容" @click="show=true"></u-search>
|
||||
</view>
|
||||
<u-line dashed></u-line>
|
||||
<view class="info-item" v-for="(item,index) in dataList" :key="index">
|
||||
$foreach(column in genTable.Columns)
|
||||
$set(labelName = column.ColumnComment)
|
||||
$set(columnName = column.CsharpFieldFl)
|
||||
$if(column.IsList == true)
|
||||
|
||||
$if(column.HtmlType == "imageUpload")
|
||||
<view class="info-line">
|
||||
<text class="label-name">${labelName}</text>
|
||||
<imagePreview :src="item.${columnName}"></imagePreview>
|
||||
</view>
|
||||
$elseif(column.HtmlType == "checkbox" || column.HtmlType == "select" || column.HtmlType == "radio")
|
||||
<view class="info-line">
|
||||
<text class="label-name">${labelName}</text>
|
||||
$if(column.HtmlType == "checkbox")
|
||||
<dict-tag :options="$if(column.DictType != "") dict.type.${column.DictType} $else ${column.CsharpFieldFl}Options$end" :value="item.${columnName} ? item.${columnName}.split(',') : []" />
|
||||
$else
|
||||
<dict-tag :options="$if(column.DictType != "") dict.type.${column.DictType} $else ${column.CsharpFieldFl}Options$end" :value="item.${columnName}" />
|
||||
$end
|
||||
</view>
|
||||
$else
|
||||
<view class="info-line">
|
||||
<text class="label-name">${labelName}</text>
|
||||
<text>{{item.${columnName}}}</text>
|
||||
</view>
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
<view class="info-btn-wrap justify-end">
|
||||
$if(replaceDto.ShowBtnView)
|
||||
<view class="tag-item">
|
||||
<u-tag text="详情" plain shape="circle" type="info" icon="eye" @click="handleView(item)"
|
||||
v-if="checkPermi(['${replaceDto.PermissionPrefix}:query'])"></u-tag>
|
||||
</view>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
<view class="tag-item">
|
||||
<u-tag text="编辑" plain shape="circle" icon="edit-pen" @click="handleEdit(item)"
|
||||
v-if="checkPermi(['${replaceDto.PermissionPrefix}:edit'])"></u-tag>
|
||||
</view>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnDelete || replaceDto.ShowBtnMultiDel)
|
||||
<view class="tag-item">
|
||||
<u-tag text="删除" class="tag-item" plain shape="circle" type="error" icon="trash"
|
||||
v-if="checkPermi(['userinfo:delete'])" @click="handleDelete(item)"></u-tag>
|
||||
</view>
|
||||
$end
|
||||
</view>
|
||||
<u-line dashed></u-line>
|
||||
</view>
|
||||
<view class="page-footer">
|
||||
<u-empty mode="list" :marginTop="140" v-if="total == 0"></u-empty>
|
||||
<uni-pagination v-else show-icon="true" :total="total" :pageSize="queryParams.pageSize"
|
||||
:current="queryParams.pageNum" @change="getData"></uni-pagination>
|
||||
<view class="text-grey padding text-center"> 共 {{ total }}条数据 </view>
|
||||
</view>
|
||||
|
||||
<u-popup :show="show" mode="bottom" @close="show = false" @open="show = true">
|
||||
<view class="search-form">
|
||||
<view class="search-title">搜索</view>
|
||||
<u--form labelPosition="left" :model="queryParams" labelWidth="100px" ref="uForm">
|
||||
<u-form-item label="排序字段" prop="sort" borderBottom>
|
||||
<uni-data-select v-model="queryParams.sort" :clear="true" :localdata="sortOptions"
|
||||
format="{label}"></uni-data-select>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="排序方式" prop="sortType" borderBottom ref="item1">
|
||||
<u-radio-group v-model="queryParams.sortType">
|
||||
<u-radio label="升序" name="asc" :customStyle="{marginRight: '20px'}"></u-radio>
|
||||
<u-radio label="倒序" name="desc"></u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
<u-gap height="30"></u-gap>
|
||||
$foreach(column in genTable.Columns)
|
||||
$set(labelName = "")
|
||||
$set(columnName = "")
|
||||
$if(column.IsQuery == true)
|
||||
$set(columnName = column.CsharpFieldFl)
|
||||
$if(column.ColumnComment != "")
|
||||
$set(labelName = column.ColumnComment)
|
||||
$else
|
||||
$set(labelName = column.CsharpFieldFl)
|
||||
$end
|
||||
|
||||
$if(column.HtmlType == "datetime")
|
||||
<u-form-item label="时间查询">
|
||||
<uni-datetime-picker :border="false" v-model="dateRange${column.CsharpField}" type="daterange" @change="${column.CsharpFieldFl}Select" />
|
||||
</u-form-item>
|
||||
$elseif(column.HtmlType == "radio" || column.HtmlType == "select")
|
||||
<u-form-item label="${labelName}" prop="${column.CsharpFieldFl}" borderBottom ref="item2">
|
||||
<view class="tag-wrap">
|
||||
<view class="tag-item">
|
||||
<u-tag text="全部" :plain="null != queryParams.${column.CsharpFieldFl}" name="" @click="queryParams.${column.CsharpFieldFl} = null">
|
||||
</u-tag>
|
||||
</view>
|
||||
<view class="tag-item" v-for="(item, index) in $if(column.DictType != "") dict.type.${column.DictType} $else ${column.CsharpFieldFl}Options$end" :key="index">
|
||||
<u-tag :text="item.label" :plain="item.value != queryParams.${column.CsharpFieldFl}" :name="item.value"
|
||||
@click="${column.CsharpFieldFl}Select(item)">
|
||||
</u-tag>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
$else
|
||||
<u-form-item label="${labelName}" prop="${column.CsharpFieldFl}" borderBottom ref="item1">
|
||||
<u--input v-model="queryParams.${column.CsharpFieldFl}" border="none" placeholder="请输入${labelName}"></u--input>
|
||||
</u-form-item>
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
</u--form>
|
||||
|
||||
<view class="btn-group">
|
||||
<u-button text="重置" icon="reload" :customStyle="{marginRight: '10px'}" shape="circle" type="success"
|
||||
@click="resetQuery"></u-button>
|
||||
<u-button text="搜索" icon="search" shape="circle" type="primary" @click="handleQuery"></u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<u-back-top :scroll-top="scrollTop" :bottom="180"></u-back-top>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
checkPermi
|
||||
} from '@/utils/permission.js'
|
||||
import "@/static/scss/page.scss";
|
||||
import {
|
||||
list${genTable.BusinessName},
|
||||
$if(replaceDto.ShowBtnDelete)
|
||||
del${genTable.BusinessName},
|
||||
$end
|
||||
}
|
||||
from '@/api/${tool.FirstLowerCase(genTable.ModuleName)}/${genTable.BusinessName.ToLower()}.js'
|
||||
|
||||
import {
|
||||
getDate
|
||||
} from '@/utils/common.js'
|
||||
export default {
|
||||
dicts: [
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "radio" || item.HtmlType.Contains("select") || item.HtmlType == "checkbox") && item.DictType != "")
|
||||
"${item.DictType}",
|
||||
$end
|
||||
$end
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
scrollTop: 0,
|
||||
dataList: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
sortType: 'desc',
|
||||
sort: undefined,
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.IsQuery == true)
|
||||
${item.CsharpFieldFl}: undefined,
|
||||
$end
|
||||
$end
|
||||
},
|
||||
total: 0,
|
||||
show: false,
|
||||
loading: false,
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "radio" || item.HtmlType == "select" || item.HtmlType == "checkbox") && item.DictType == "")
|
||||
// ${item.ColumnComment}选项列表 格式 eg:{ label: '标签', value: '0'}
|
||||
${item.CsharpFieldFl}Options: [],
|
||||
$elseif(item.HtmlType == "datetime" && item.IsQuery == true)
|
||||
//${item.ColumnComment}时间范围
|
||||
dateRange${item.CsharpField}: [],
|
||||
$end
|
||||
$end
|
||||
// 排序集合 格式 eg:{ label: '名称', value: 'userId'}
|
||||
sortOptions: [
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.IsSort)
|
||||
{
|
||||
label: '${column.ColumnComment}',
|
||||
value: '${column.CsharpFieldFl}'
|
||||
},
|
||||
$end
|
||||
$end
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
checkPermi,
|
||||
getList() {
|
||||
uni.showLoading({
|
||||
title: 'loading...'
|
||||
});
|
||||
$foreach(item in genTable.Columns)
|
||||
$if(item.HtmlType == "datetime" && item.IsQuery == true)
|
||||
this.addDateRange(this.queryParams, this.dateRange${item.CsharpField}, '${item.CsharpField}');
|
||||
$end
|
||||
$end
|
||||
list${genTable.BusinessName}(this.queryParams).then(res => {
|
||||
if (res.code == 200) {
|
||||
this.dataList = [...this.dataList, ...res.data.result]
|
||||
this.total = res.data.totalNum;
|
||||
}
|
||||
})
|
||||
},
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
handleAdd() {
|
||||
this.${tab}tab.navigateTo('./edit?opertype=1')
|
||||
},
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
handleEdit(e) {
|
||||
this.${tab}tab.navigateTo('./edit?opertype=2&${replaceDto.FistLowerPk}=' + e.id)
|
||||
},
|
||||
$end
|
||||
$if(replaceDto.ShowBtnView)
|
||||
handleView(e) {
|
||||
this.${tab}tab.navigateTo('./edit?opertype=3&${replaceDto.FistLowerPk}=' + e.id)
|
||||
},
|
||||
$end
|
||||
$if(replaceDto.ShowBtnDelete || replaceDto.ShowBtnMultiDel)
|
||||
handleDelete(row) {
|
||||
const Ids = row.${replaceDto.FistLowerPk};
|
||||
|
||||
this.${modal}modal.confirm('你确定要删除吗?').then(() => {
|
||||
return del${genTable.BusinessName}(Ids);
|
||||
})
|
||||
.then(() => {
|
||||
this.handleQuery();
|
||||
this.${modal}modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
$end
|
||||
resetQuery() {
|
||||
this.${refs}refs.uForm.resetFields()
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.HtmlType == "datetime" && column.IsQuery == true)
|
||||
this.dateRange${column.CsharpField} = []
|
||||
$end
|
||||
$end
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.dataList = []
|
||||
uni.startPullDownRefresh();
|
||||
this.getList()
|
||||
this.show = false
|
||||
},
|
||||
getData(e) {
|
||||
this.queryParams.pageNum = e.current
|
||||
this.getList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
uni.stopPullDownRefresh()
|
||||
this.handleQuery()
|
||||
},
|
||||
$foreach(column in genTable.Columns)
|
||||
$if(column.IsQuery == true)
|
||||
$if(column.HtmlType == "datetime")
|
||||
${column.CsharpFieldFl}Select(e) {
|
||||
this.${column.CsharpFieldFl} = e
|
||||
},
|
||||
$elseif(column.HtmlType == "radio" || column.HtmlType == "select")
|
||||
${column.CsharpFieldFl}Select(e) {
|
||||
this.queryParams.${column.CsharpFieldFl} = e.value
|
||||
},
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
onPageScroll(e) {
|
||||
this.scrollTop = e.scrollTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -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">
|
||||
@ -108,6 +109,25 @@ $if(replaceDto.ShowBtnTruncate)
|
||||
</el-button>
|
||||
</el-col>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
<el-col :span="1.5">
|
||||
<el-dropdown trigger="click" v-hasPermi="['${replaceDto.PermissionPrefix}:import']">
|
||||
<el-button type="primary" plain icon="Upload">
|
||||
{{ ${t}t('btn.import') }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="upload">
|
||||
<importData
|
||||
templateUrl="${genTable.ModuleName}/${genTable.BusinessName}/importTemplate"
|
||||
importUrl="/${genTable.ModuleName}/${genTable.BusinessName}/importData"
|
||||
@success="handleFileSuccess"></importData>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-col>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnExport)
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="download" @click="handleExport" v-hasPermi="['${replaceDto.PermissionPrefix}:export']">
|
||||
@ -118,13 +138,13 @@ $end
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据区域 -->
|
||||
<el-table
|
||||
:data="dataList"
|
||||
v-loading="loading"
|
||||
ref="table"
|
||||
border
|
||||
highlight-current-row
|
||||
<el-table
|
||||
:data="dataList"
|
||||
v-loading="loading"
|
||||
ref="table"
|
||||
border
|
||||
header-cell-class-name="el-table-header-cell"
|
||||
highlight-current-row
|
||||
@sort-change="sortChange"
|
||||
$if(replaceDto.ShowBtnMultiDel)
|
||||
@selection-change="handleSelectionChange"
|
||||
@ -133,27 +153,10 @@ $end
|
||||
$if(replaceDto.ShowBtnMultiDel)
|
||||
<el-table-column type="selection" width="50" align="center"/>
|
||||
$end
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName && genTable.TplCategory == "subNav")
|
||||
<el-table-column type="expand">
|
||||
<template #default="props">
|
||||
<el-descriptions border>
|
||||
$foreach(subColumn in genSubTable.Columns)
|
||||
<el-descriptions-item label="${subColumn.ColumnComment}">{{ props.row.$tool.FirstLowerCase(genTable.SubTable.ClassName)Nav.${subColumn.CsharpFieldFl} }}</el-descriptions-item>
|
||||
$end
|
||||
</el-descriptions>
|
||||
</template>
|
||||
</el-table-column>
|
||||
$end
|
||||
$if(null != genTable.SubTableName && "" != genTable.SubTableName && genTable.TplCategory == "subNavMore")
|
||||
<el-table-column type="expand">
|
||||
<template #default="props">
|
||||
<el-table :data="props.row.$tool.FirstLowerCase(genTable.SubTable.ClassName)Nav" header-row-class-name="text-navy">
|
||||
$foreach(subColumn in genSubTable.Columns)
|
||||
$if(subColumn.IsList == true)
|
||||
<el-table-column prop="${subColumn.CsharpFieldFl}" label="${subColumn.ColumnComment}" align="center"/>
|
||||
$end
|
||||
$end
|
||||
</el-table>
|
||||
$if(sub)
|
||||
<el-table-column align="center" width="90">
|
||||
<template #default="scope">
|
||||
<el-button text @click="rowClick(scope.row)">{{ ${t}t('btn.details') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
$end
|
||||
@ -185,11 +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">
|
||||
$if(column.HtmlType == "checkbox")
|
||||
<dict-tag :options="$if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :value="scope.row.${columnName} ? scope.row.${columnName}.split(',') : []" />
|
||||
$else
|
||||
<dict-tag :options="$if(column.DictType != "") options.${column.DictType} $else options.${column.CsharpFieldFl}Options$end" :value="scope.row.${columnName}" />
|
||||
$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")
|
||||
@ -199,24 +198,61 @@ $else
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
<el-table-column label="操作" align="center" width="160">
|
||||
<el-table-column label="操作" width="160">
|
||||
<template #default="scope">
|
||||
$if(replaceDto.OperBtnStyle == 2)
|
||||
<el-button-group>
|
||||
$if(replaceDto.ShowBtnView)
|
||||
<el-button type="primary" icon="view" @click="handlePreview(scope.row)"></el-button>
|
||||
<el-button text type="primary" icon="view" @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 text v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" type="success" icon="edit" title="编辑" @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 text v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" type="danger" icon="delete" title="删除" @click="handleDelete(scope.row)"></el-button>
|
||||
$end
|
||||
</el-button-group>
|
||||
$else
|
||||
$if(replaceDto.ShowBtnView)
|
||||
<el-button type="primary" size="small" icon="view" title="详情" @click="handlePreview(scope.row)"></el-button>
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
<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 type="danger" size="small" icon="delete" title="删除" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" @click="handleDelete(scope.row)"></el-button>
|
||||
$end
|
||||
$end
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination class="mt10" background :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
$* 一对一/一对多列表显示详情 *$
|
||||
$if(sub)
|
||||
<el-drawer v-model="drawer" :with-header="false" direction="btt">
|
||||
<el-table :data="$tool.FirstLowerCase(genTable.SubTable.ClassName)List" header-row-class-name="text-navy">
|
||||
<el-table-column label="序号" type="index" width="80" />
|
||||
$foreach(column in genSubTable.Columns)
|
||||
$set(columnName = column.CsharpFieldFl)
|
||||
$if(column.IsList == true)
|
||||
$if(column.HtmlType == "checkbox" || column.HtmlType.Contains("select") || column.HtmlType == "radio")
|
||||
<el-table-column prop="${columnName}" label="${column.ColumnComment}">
|
||||
<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 />
|
||||
</template>
|
||||
</el-table-column>
|
||||
$else
|
||||
<el-table-column prop="${column.CsharpFieldFl}" label="${column.ColumnComment}"/>
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
$end
|
||||
|
||||
<!-- 添加或修改${genTable.functionName}对话框 -->
|
||||
<el-dialog :title="title" :lock-scroll="false" v-model="open" >
|
||||
<el-dialog :title="title" :lock-scroll="false" v-model="open" ${if(sub)}:fullscreen="fullScreen"$end>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-row :gutter="20">
|
||||
$foreach(column in genTable.Columns)
|
||||
@ -227,6 +263,7 @@ $set(labelName = column.ColumnComment)
|
||||
$if(column.CsharpType == "int" || column.CsharpType == "long")
|
||||
$set(value = "parseInt(item.dictValue)")
|
||||
$set(number = ".number")
|
||||
$set(switchType = ":active-value='1' :inactive-value='0'")
|
||||
$end
|
||||
|
||||
$if(column.IsPK || column.IsIncrement)
|
||||
@ -272,7 +309,9 @@ $elseif(column.HtmlType == "radio" || column.HtmlType == "selectRadio")
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-radio-group v-model="form.${columnName}"${column.DisabledStr}>
|
||||
<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>
|
||||
<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>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -288,11 +327,17 @@ $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-option
|
||||
<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"
|
||||
:label="item.dictLabel"
|
||||
@ -316,6 +361,12 @@ $elseif(column.HtmlType == "colorPicker")
|
||||
<el-color-picker v-model="form.${columnName}" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$elseif(column.HtmlType == "switch")
|
||||
<el-col :lg="12">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
<el-switch v-model="form.${columnName}" ${switchType} />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
$else
|
||||
<el-col :lg="${options.ColNum}">
|
||||
<el-form-item label="${labelName}" prop="${columnName}">
|
||||
@ -326,10 +377,81 @@ $end
|
||||
$end
|
||||
$end
|
||||
</el-row>
|
||||
$* 子表信息 *$
|
||||
$if(sub)
|
||||
<el-divider content-position="center">${genTable.SubTable.FunctionName}信息</el-divider>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd${genTable.SubTable.ClassName}">添加</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" icon="Delete" @click="handleDelete${genTable.SubTable.ClassName}">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" icon="FullScreen" @click="fullScreen = !fullScreen">{{ fullScreen ? '退出全屏' : '全屏' }}</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table :data="${tool.FirstLowerCase(genTable.SubTable.ClassName)}List" :row-class-name="row${genTable.SubTable.ClassName}Index" @selection-change="handle${genTable.SubTable.ClassName}SelectionChange" ref="${genTable.SubTable.ClassName}Ref">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column label="序号" align="center" prop="index" width="50"/>
|
||||
$foreach(column in genTable.SubTable.Columns)
|
||||
$set(labelName = column.ColumnComment)
|
||||
$set(columnName = column.CsharpFieldFl)
|
||||
$set(value = "item.dictValue")
|
||||
$if(column.CsharpType == "int" || column.CsharpType == "long")
|
||||
$set(value = "parseInt(item.dictValue)")
|
||||
$set(number = ".number")
|
||||
$set(switchType = ":active-value='1' :inactive-value='0'")
|
||||
$end
|
||||
$if(column.IsList == true)
|
||||
$if(column.IsPk || column.CsharpField == genTable.SubTableFkName)
|
||||
$elseif(column.HtmlType == "inputNumber" || column.HtmlType == "customInput")
|
||||
<el-table-column label="${labelName}" align="center" prop="${columnName}" width="140">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.${columnName}" controls-position="right" placeholder="请输入${labelName}" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
$elseif(column.HtmlType == "datetime" || column.HtmlType == "month")
|
||||
<el-table-column label="${labelName}" align="center" prop="${columnName}">
|
||||
<template #default="scope">
|
||||
<el-date-picker clearable v-model="scope.row.${columnName}" type="date" placeholder="选择日期时间"></el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
$elseif(column.HtmlType == "radio" || column.HtmlType == "selectRadio" || column.HtmlType == "select" || column.HtmlType == "selectMulti")
|
||||
<el-table-column label="${labelName}" prop="${columnName}">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.${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>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
$elseif(column.HtmlType == "switch")
|
||||
<el-table-column label="${labelName}" prop="${columnName}">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.${columnName}" ${switchType} />
|
||||
</template>
|
||||
</el-table-column>
|
||||
$else
|
||||
<el-table-column label="${labelName}" align="center" prop="${columnName}">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.${columnName}" placeholder="请输入${labelName}" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
$end
|
||||
$end
|
||||
$end
|
||||
</el-table>
|
||||
$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>
|
||||
@ -347,7 +469,9 @@ from '@/api/${tool.FirstLowerCase(genTable.ModuleName)}/${genTable.BusinessName.
|
||||
$if(replaceDto.ShowEditor == 1)
|
||||
import Editor from '@/components/Editor'
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
import importData from '@/components/ImportData'
|
||||
$end
|
||||
const { proxy } = getCurrentInstance()
|
||||
const ids = ref([])
|
||||
const loading = ref(false)
|
||||
@ -419,8 +543,8 @@ $end
|
||||
|
||||
$set(index = 0)
|
||||
var dictParams = [
|
||||
$foreach(item in genTable.Columns)
|
||||
$if((item.HtmlType == "radio" || item.HtmlType.Contains("select") || item.HtmlType == "checkbox") && item.DictType != "")
|
||||
$foreach(item in dicts)
|
||||
$if(item.DictType != "")
|
||||
{ dictType: "${item.DictType}" },
|
||||
$set(index = index + 1)
|
||||
$end
|
||||
@ -518,7 +642,7 @@ $end
|
||||
$end
|
||||
},
|
||||
options: {
|
||||
$foreach(column in genTable.Columns)
|
||||
$foreach(column in dicts)
|
||||
$if(column.HtmlType == "radio" || column.HtmlType.Contains("select") || column.HtmlType == "checkbox")
|
||||
//$if(column.ColumnComment != "") ${column.ColumnComment} $else ${column.CsharpFieldFl}$end选项列表 格式 eg:{ dictLabel: '标签', dictValue: '0'}
|
||||
$if(column.DictType != "")${column.DictType}$else${column.CsharpFieldFl}Options$end: [],
|
||||
@ -539,24 +663,28 @@ 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: undefined,
|
||||
$item.CsharpFieldFl: null,
|
||||
$end
|
||||
$end
|
||||
};
|
||||
$if(sub)
|
||||
${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value = []
|
||||
$end
|
||||
proxy.resetForm("formRef")
|
||||
}
|
||||
|
||||
$if(replaceDto.ShowBtnAdd)
|
||||
// 添加按钮操作
|
||||
function handleAdd() {
|
||||
reset();
|
||||
open.value = true
|
||||
title.value = '添加'
|
||||
title.value = '添加${genTable.functionName}'
|
||||
opertype.value = 1
|
||||
}
|
||||
|
||||
$end
|
||||
$if(replaceDto.ShowBtnEdit)
|
||||
// 修改按钮操作
|
||||
function handleUpdate(row) {
|
||||
reset()
|
||||
@ -565,49 +693,60 @@ function handleUpdate(row) {
|
||||
const { code, data } = res
|
||||
if (code == 200) {
|
||||
open.value = true
|
||||
title.value = "修改数据"
|
||||
title.value = '修改${genTable.functionName}'
|
||||
opertype.value = 2
|
||||
|
||||
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
|
||||
}
|
||||
$if(sub)
|
||||
${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value = res.data.${tool.FirstLowerCase(genTable.SubTable.ClassName)}Nav
|
||||
$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
|
||||
|
||||
$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
|
||||
@ -621,8 +760,8 @@ function handleDelete(row) {
|
||||
getList()
|
||||
proxy.${modal}modal.msgSuccess("删除成功")
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnTruncate)
|
||||
// 清空
|
||||
@ -653,7 +792,22 @@ function handlePreview(row) {
|
||||
open.value = true
|
||||
title.value = '查看'
|
||||
opertype.value = 3
|
||||
form.value = row
|
||||
form.value = { ...row }
|
||||
}
|
||||
$end
|
||||
|
||||
$if(replaceDto.ShowBtnImport)
|
||||
// 导入数据成功处理
|
||||
const handleFileSuccess = (response) => {
|
||||
const { item1, item2 } = response.data
|
||||
var error = ''
|
||||
item2.forEach((item) => {
|
||||
error += item.storageMessage + ','
|
||||
})
|
||||
proxy.${alert}alert(item1 + '<p>' + error + '</p>', '导入结果', {
|
||||
dangerouslyUseHTMLString: true
|
||||
})
|
||||
getList()
|
||||
}
|
||||
$end
|
||||
|
||||
@ -672,5 +826,61 @@ function handleExport() {
|
||||
}
|
||||
$end
|
||||
|
||||
$if(sub)
|
||||
/*********************${genTable.SubTable.FunctionName}子表信息*************************/
|
||||
const ${tool.FirstLowerCase(genTable.SubTable.ClassName)}List = ref([])
|
||||
const checked${genTable.SubTable.ClassName} = ref([])
|
||||
const fullScreen = ref(false)
|
||||
const drawer = ref(false)
|
||||
|
||||
/** ${genTable.SubTable.FunctionName}序号 */
|
||||
function row${genTable.SubTable.ClassName}Index({ row, rowIndex }) {
|
||||
row.index = rowIndex + 1;
|
||||
}
|
||||
|
||||
/** ${genTable.SubTable.FunctionName}添加按钮操作 */
|
||||
function handleAdd${genTable.SubTable.ClassName}() {
|
||||
let obj = {};
|
||||
$foreach(column in genTable.SubTable.Columns)
|
||||
$if(column.IsPK || column.CsharpField == genTable.SubTableFkName)
|
||||
$elseif(column.IsList == true && "" != column.CsharpField)
|
||||
//obj.${column.CsharpFieldFl} = null;
|
||||
$end
|
||||
$end
|
||||
${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value.push(obj);
|
||||
}
|
||||
|
||||
/** 复选框选中数据 */
|
||||
function handle${genTable.SubTable.ClassName}SelectionChange(selection) {
|
||||
checked${genTable.SubTable.ClassName}.value = selection.map(item => item.index)
|
||||
}
|
||||
|
||||
/** ${genTable.SubTable.FunctionName}删除按钮操作 */
|
||||
function handleDelete${genTable.SubTable.ClassName}() {
|
||||
if(checked${genTable.SubTable.ClassName}.value.length == 0){
|
||||
proxy.${modal}modal.msgError('请先选择要删除的${genTable.SubTable.FunctionName}数据')
|
||||
} else {
|
||||
const ${genTable.SubTable.ClassName}s = ${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value;
|
||||
const checked${genTable.SubTable.ClassName}s = checked${genTable.SubTable.ClassName}.value;
|
||||
${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value = ${genTable.SubTable.ClassName}s.filter(function(item) {
|
||||
return checked${genTable.SubTable.ClassName}s.indexOf(item.index) == -1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** ${genTable.SubTable.FunctionName}详情 */
|
||||
function rowClick(row) {
|
||||
const id = row.${replaceDto.FistLowerPk} || ids.value
|
||||
get${genTable.BusinessName}(id).then((res) => {
|
||||
const { code, data } = res
|
||||
if (code == 200) {
|
||||
drawer.value = true
|
||||
${tool.FirstLowerCase(genTable.SubTable.ClassName)}List.value = data.${tool.FirstLowerCase(genTable.SubTable.ClassName)}Nav
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$end
|
||||
|
||||
handleQuery()
|
||||
</script>
|
||||
BIN
ZR.Admin.WebApi/wwwroot/ImportTemplate/lang.xlsx
Normal file
BIN
ZR.Admin.WebApi/wwwroot/ImportTemplate/lang.xlsx
Normal file
Binary file not shown.
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
|
||||
@ -26,11 +27,11 @@ namespace ZR.CodeGenerator
|
||||
/// <param name="dto"></param>
|
||||
public static void Generate(GenerateDto dto)
|
||||
{
|
||||
var vuePath = AppSettings.GetConfig("gen:vuePath");
|
||||
var genOptions = AppSettings.Get<Gen>("gen");
|
||||
dto.VueParentPath = dto.VueVersion == 3 ? "ZRAdmin-vue" : "ZR.Vue";
|
||||
if (!vuePath.IsEmpty())
|
||||
if (!genOptions.VuePath.IsEmpty())
|
||||
{
|
||||
dto.VueParentPath = vuePath;
|
||||
dto.VueParentPath = genOptions.VuePath;
|
||||
}
|
||||
dto.GenOptions = GenerateOption(dto.GenTable);
|
||||
if (dto.GenTable.SubTable != null)
|
||||
@ -50,7 +51,9 @@ namespace ZR.CodeGenerator
|
||||
ShowBtnView = dto.GenTable.Options.CheckedBtn.Any(f => f == 5),
|
||||
ShowBtnTruncate = dto.GenTable.Options.CheckedBtn.Any(f => f == 6),
|
||||
ShowBtnMultiDel = dto.GenTable.Options.CheckedBtn.Any(f => f == 7),
|
||||
ViewFileName = dto.GenTable.BusinessName.FirstUpperCase()
|
||||
ShowBtnImport = dto.GenTable.Options.CheckedBtn.Any(f => f == 8),
|
||||
ViewFileName = dto.GenTable.BusinessName.FirstUpperCase(),
|
||||
OperBtnStyle = dto.GenTable.Options.OperBtnStyle
|
||||
};
|
||||
var columns = dto.GenTable.Columns;
|
||||
|
||||
@ -80,14 +83,13 @@ namespace ZR.CodeGenerator
|
||||
}
|
||||
GenerateVueJs(dto);
|
||||
GenerateSql(dto);
|
||||
dto.ReplaceDto = replaceDto;
|
||||
if (dto.IsPreview) return;
|
||||
|
||||
foreach (var item in dto.GenCodes)
|
||||
if (genOptions.ShowApp)
|
||||
{
|
||||
item.Path = Path.Combine(dto.GenCodePath, item.Path);
|
||||
FileUtil.WriteAndSave(item.Path, item.Content);
|
||||
GenerateAppVueViews(replaceDto, dto);
|
||||
GenerateAppVueFormViews(replaceDto, dto);
|
||||
GenerateAppJs(dto);
|
||||
}
|
||||
dto.ReplaceDto = replaceDto;
|
||||
}
|
||||
|
||||
private static CodeGenerateOption GenerateOption(GenTable genTable)
|
||||
@ -284,6 +286,52 @@ namespace ZR.CodeGenerator
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region app页面
|
||||
|
||||
/// <summary>
|
||||
/// 列表页面
|
||||
/// </summary>
|
||||
/// <param name="generateDto"></param>
|
||||
private static void GenerateAppVueViews(ReplaceDto replaceDto, GenerateDto generateDto)
|
||||
{
|
||||
var fileName = Path.Combine("app", "vue2.txt");
|
||||
var tpl = JnHelper.ReadTemplate(CodeTemplateDir, fileName);
|
||||
|
||||
tpl.Set("options", generateDto.GenTable?.Options);
|
||||
|
||||
var result = tpl.Render();
|
||||
var fullPath = Path.Combine(generateDto.AppVuePath, "pages", generateDto.GenTable.ModuleName.FirstLowerCase(), $"{replaceDto.ViewFileName.FirstLowerCase()}", "index.vue");
|
||||
generateDto.GenCodes.Add(new GenCode(20, "uniapp页面", fullPath, result));
|
||||
}
|
||||
private static void GenerateAppVueFormViews(ReplaceDto replaceDto, GenerateDto generateDto)
|
||||
{
|
||||
var fileName = Path.Combine("app", "form.txt");
|
||||
var tpl = JnHelper.ReadTemplate(CodeTemplateDir, fileName);
|
||||
|
||||
tpl.Set("options", generateDto.GenTable?.Options);
|
||||
|
||||
var result = tpl.Render();
|
||||
var fullPath = Path.Combine(generateDto.AppVuePath, "pages", generateDto.GenTable.ModuleName.FirstLowerCase(), $"{replaceDto.ViewFileName.FirstLowerCase()}", "edit.vue");
|
||||
generateDto.GenCodes.Add(new GenCode(20, "uniapp表单", fullPath, result));
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成vue页面api
|
||||
/// </summary>
|
||||
/// <param name="generateDto"></param>
|
||||
/// <returns></returns>
|
||||
public static void GenerateAppJs(GenerateDto generateDto)
|
||||
{
|
||||
var filePath = Path.Combine("app", "api.txt");
|
||||
var tpl = JnHelper.ReadTemplate(CodeTemplateDir, filePath);
|
||||
var result = tpl.Render();
|
||||
|
||||
string fileName = generateDto.GenTable.BusinessName.ToLower() + ".js";
|
||||
string fullPath = Path.Combine(generateDto.AppVuePath, "api", generateDto.GenTable.ModuleName.FirstLowerCase(), fileName);
|
||||
|
||||
generateDto.GenCodes.Add(new GenCode(21, "uniapp Api", fullPath, result));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 帮助方法
|
||||
|
||||
/// <summary>
|
||||
@ -334,23 +382,36 @@ namespace ZR.CodeGenerator
|
||||
/// 获取C# 类型
|
||||
/// </summary>
|
||||
/// <param name="sDatatype"></param>
|
||||
/// <param name="csharpType"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetCSharpDatatype(string sDatatype)
|
||||
public static CSharpDataType GetCSharpDatatype(string sDatatype, CsharpTypeArr csharpType)
|
||||
{
|
||||
sDatatype = sDatatype.ToLower();
|
||||
string sTempDatatype = sDatatype switch
|
||||
if (csharpType.Int.Contains(sDatatype))
|
||||
{
|
||||
"int" or "integer" or "smallint" or "int4" or "int8" or "int2" => "int",
|
||||
"bigint" or "number" => "long",
|
||||
"tinyint" => "byte",
|
||||
"numeric" or "real" or "float" => "float",
|
||||
"decimal" or "numer(8,2)" or "numeric" => "decimal",
|
||||
"bit" => "bool",
|
||||
"date" or "datetime" or "datetime2" or "smalldatetime" or "timestamp" => "DateTime",
|
||||
"money" or "smallmoney" => "decimal",
|
||||
_ => "string",
|
||||
};
|
||||
return sTempDatatype;
|
||||
return CSharpDataType.@int;
|
||||
}
|
||||
else if (csharpType.Long.Contains(sDatatype))
|
||||
{
|
||||
return CSharpDataType.@long;
|
||||
}
|
||||
else if (csharpType.Float.Contains(sDatatype))
|
||||
{
|
||||
return CSharpDataType.@float;
|
||||
}
|
||||
else if (csharpType.Decimal.Contains(sDatatype))
|
||||
{
|
||||
return CSharpDataType.@decimal;
|
||||
}
|
||||
else if (csharpType.DateTime.Contains(sDatatype))
|
||||
{
|
||||
return CSharpDataType.DateTime;
|
||||
}
|
||||
else if (csharpType.Bool.Contains(sDatatype))
|
||||
{
|
||||
return CSharpDataType.@bool;
|
||||
}
|
||||
return CSharpDataType.@string;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -398,10 +459,18 @@ namespace ZR.CodeGenerator
|
||||
/// <param name="seqs"></param>
|
||||
public static List<GenTableColumn> InitGenTableColumn(GenTable genTable, List<DbColumnInfo> dbColumnInfos, List<OracleSeq> seqs = null)
|
||||
{
|
||||
OptionsSetting optionsSetting = new();
|
||||
|
||||
var gen = AppSettings.Get<Gen>("gen");
|
||||
var dbConfig = AppSettings.Get<DbConfigs>("CodeGenDbConfig");
|
||||
|
||||
optionsSetting.CodeGenDbConfig = dbConfig;
|
||||
optionsSetting.Gen = gen ?? throw new CustomException("代码生成节点配置异常");
|
||||
optionsSetting.Gen.GenDbConfig = dbConfig ?? throw new CustomException("代码生成节点数据配置异常");
|
||||
List<GenTableColumn> genTableColumns = new();
|
||||
foreach (var column in dbColumnInfos)
|
||||
{
|
||||
genTableColumns.Add(InitColumnField(genTable, column, seqs));
|
||||
genTableColumns.Add(InitColumnField(genTable, column, seqs, optionsSetting));
|
||||
}
|
||||
return genTableColumns;
|
||||
}
|
||||
@ -411,12 +480,13 @@ namespace ZR.CodeGenerator
|
||||
/// </summary>
|
||||
/// <param name="genTable"></param>
|
||||
/// <param name="column"></param>
|
||||
/// <param name="optionsSetting"></param>
|
||||
/// <param name="seqs">oracle 序列</param>
|
||||
/// <returns></returns>
|
||||
private static GenTableColumn InitColumnField(GenTable genTable, DbColumnInfo column, List<OracleSeq> seqs)
|
||||
private static GenTableColumn InitColumnField(GenTable genTable, DbColumnInfo column, List<OracleSeq> seqs, OptionsSetting optionsSetting)
|
||||
{
|
||||
var dbConfig = AppSettings.Get<List<DbConfigs>>("dbConfigs").FirstOrDefault(f => f.IsGenerateDb);
|
||||
var dataType = column.DataType;
|
||||
if (dbConfig.DbType == 3)
|
||||
if (optionsSetting.Gen.GenDbConfig.DbType == 3)
|
||||
{
|
||||
dataType = column.OracleDataType;
|
||||
var seqName = $"SEQ_{genTable.TableName}_{column.DbColumnName}";
|
||||
@ -431,7 +501,7 @@ namespace ZR.CodeGenerator
|
||||
ColumnType = dataType,
|
||||
TableId = genTable.TableId,
|
||||
TableName = genTable.TableName,
|
||||
CsharpType = GetCSharpDatatype(dataType),
|
||||
CsharpType = GetCSharpDatatype(dataType, optionsSetting.Gen.CsharpTypeArr).ToString(),
|
||||
CsharpField = column.DbColumnName.ConvertToPascal("_"),
|
||||
IsRequired = !column.IsNullable,
|
||||
IsIncrement = column.IsIdentity,
|
||||
@ -494,9 +564,22 @@ namespace ZR.CodeGenerator
|
||||
/// <param name="replaceDto"></param>
|
||||
private static void InitJntTemplate(GenerateDto dto, ReplaceDto replaceDto)
|
||||
{
|
||||
#if DEBUG
|
||||
Engine.Current.Clean();
|
||||
#endif
|
||||
dto.GenTable.Columns = dto.GenTable.Columns.OrderBy(x => x.Sort).ToList();
|
||||
bool showCustomInput = dto.GenTable.Columns.Any(f => f.HtmlType.Equals(GenConstants.HTML_CUSTOM_INPUT, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
#region 查询所有字典
|
||||
var dictHtml = new string[] { GenConstants.HTML_CHECKBOX, GenConstants.HTML_RADIO, GenConstants.HTML_SELECT, GenConstants.HTML_SELECT_MULTI };
|
||||
var dicts = new List<GenTableColumn>();
|
||||
dicts.AddRange(dto.GenTable.Columns.FindAll(f => dictHtml.Contains(f.HtmlType)));
|
||||
if (dto.GenTable.SubTable != null && dto.GenTable.SubTableName.IsNotEmpty())
|
||||
{
|
||||
dicts.AddRange(dto.GenTable?.SubTable?.Columns?.FindAll(f => dictHtml.Contains(f.HtmlType)));
|
||||
}
|
||||
#endregion
|
||||
|
||||
//jnt模板引擎全局变量
|
||||
Engine.Configure((options) =>
|
||||
{
|
||||
@ -508,9 +591,11 @@ namespace ZR.CodeGenerator
|
||||
options.Data.Set("refs", "$");//特殊标签替换
|
||||
options.Data.Set("t", "$");//特殊标签替换
|
||||
options.Data.Set("modal", "$");//特殊标签替换
|
||||
options.Data.Set("alert", "$");//特殊标签替换
|
||||
options.Data.Set("index", "$");//特殊标签替换
|
||||
options.Data.Set("confirm", "$");//特殊标签替换
|
||||
options.Data.Set("nextTick", "$");
|
||||
options.Data.Set("tab", "$");
|
||||
options.Data.Set("replaceDto", replaceDto);
|
||||
options.Data.Set("options", dto.GenOptions);
|
||||
options.Data.Set("subTableOptions", dto.SubTableOptions);
|
||||
@ -519,6 +604,8 @@ namespace ZR.CodeGenerator
|
||||
options.Data.Set("showCustomInput", showCustomInput);
|
||||
options.Data.Set("tool", new CodeGeneratorTool());
|
||||
options.Data.Set("codeTool", new CodeGenerateTemplate());
|
||||
options.Data.Set("dicts", dicts);
|
||||
options.Data.Set("sub", dto.GenTable.SubTable != null && dto.GenTable.SubTableName.IsNotEmpty());
|
||||
options.EnableCache = true;
|
||||
//...其它数据
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Model;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -20,9 +21,8 @@ namespace ZR.CodeGenerator
|
||||
/// <returns></returns>
|
||||
public SqlSugarClient GetSugarDbContext(string dbName = "")
|
||||
{
|
||||
List<DbConfigs> dbConfigs = AppSettings.Get<List<DbConfigs>>("dbConfigs");
|
||||
DbConfigs configs = AppSettings.Get<DbConfigs>("CodeGenDbConfig");
|
||||
|
||||
DbConfigs configs = dbConfigs.Find(f => f.IsGenerateDb == true);
|
||||
string connStr = configs.Conn;
|
||||
|
||||
if (!string.IsNullOrEmpty(dbName))
|
||||
|
||||
@ -28,7 +28,6 @@ namespace ZR.CodeGenerator
|
||||
/// </summary>
|
||||
public static readonly string[] radioFiled = new string[] { "status", "state", "is" };
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 单表(增删改查)
|
||||
/// </summary>
|
||||
@ -69,38 +68,60 @@ namespace ZR.CodeGenerator
|
||||
/// </summary>
|
||||
public static string PARENT_MENU_NAME = "parentMenuName";
|
||||
|
||||
/** 数据库字符串类型 */
|
||||
/// <summary>
|
||||
/// 数据库字符串类型
|
||||
/// </summary>
|
||||
public static string[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
||||
|
||||
/** 数据库文本类型 */
|
||||
/// <summary>
|
||||
/// 数据库文本类型
|
||||
/// </summary>
|
||||
public static string[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
|
||||
|
||||
/** 数据库时间类型 */
|
||||
/// <summary>
|
||||
/// 数据库时间类型
|
||||
/// </summary>
|
||||
public static string[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
|
||||
|
||||
/** 页面不需要编辑字段 */
|
||||
/// <summary>
|
||||
/// 页面不需要编辑字段
|
||||
/// </summary>
|
||||
public static string[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "delFlag" };
|
||||
|
||||
/** 页面不需要显示的列表字段 */
|
||||
/// <summary>
|
||||
/// 页面不需要显示的列表字段
|
||||
/// </summary>
|
||||
public static string[] COLUMNNAME_NOT_LIST = { "create_by", "create_time", "delFlag", "update_by",
|
||||
"update_time" , "password"};
|
||||
|
||||
/** 页面不需要查询字段 */
|
||||
/// <summary>
|
||||
/// 页面不需要查询字段
|
||||
/// </summary>
|
||||
public static string[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "delFlag", "update_by",
|
||||
"update_time", "remark" };
|
||||
|
||||
/** Entity基类字段 */
|
||||
/// <summary>
|
||||
/// Entity基类字段
|
||||
/// </summary>
|
||||
public static string[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
|
||||
|
||||
/** Tree基类字段 */
|
||||
/// <summary>
|
||||
/// Tree基类字段
|
||||
/// </summary>
|
||||
public static string[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
|
||||
|
||||
/** 文本框 */
|
||||
/// <summary>
|
||||
/// 文本框
|
||||
/// </summary>
|
||||
public static string HTML_INPUT = "input";
|
||||
/** 数字框 */
|
||||
/// <summary>
|
||||
/// 数字框
|
||||
/// </summary>
|
||||
public static string HTML_INPUT_NUMBER = "inputNumber";
|
||||
|
||||
/** 文本域 */
|
||||
/// <summary>
|
||||
/// 文本域
|
||||
/// </summary>
|
||||
public static string HTML_TEXTAREA = "textarea";
|
||||
|
||||
/** 下拉框 */
|
||||
@ -110,53 +131,56 @@ namespace ZR.CodeGenerator
|
||||
/// </summary>
|
||||
public static string HTML_SELECT_MULTI = "selectMulti";
|
||||
|
||||
/** 单选框 */
|
||||
/// <summary>
|
||||
/// 单选框
|
||||
/// </summary>
|
||||
public static string HTML_RADIO = "radio";
|
||||
|
||||
/** 复选框 */
|
||||
/// <summary>
|
||||
/// 复选框
|
||||
/// </summary>
|
||||
public static string HTML_CHECKBOX = "checkbox";
|
||||
|
||||
/** 日期控件 */
|
||||
/// <summary>
|
||||
/// 日期控件
|
||||
/// </summary>
|
||||
public static string HTML_DATETIME = "datetime";
|
||||
|
||||
/** 图片上传控件 */
|
||||
/// <summary>
|
||||
/// 图片上传控件
|
||||
/// </summary>
|
||||
public static string HTML_IMAGE_UPLOAD = "imageUpload";
|
||||
|
||||
/** 文件上传控件 */
|
||||
/// <summary>
|
||||
/// 文件上传控件
|
||||
/// </summary>
|
||||
public static string HTML_FILE_UPLOAD = "fileUpload";
|
||||
|
||||
/** 富文本控件 */
|
||||
/// <summary>
|
||||
/// 富文本控件
|
||||
/// </summary>
|
||||
public static string HTML_EDITOR = "editor";
|
||||
// 自定义排序
|
||||
public static string HTML_SORT = "sort";
|
||||
/// <summary>
|
||||
/// 自定义输入框
|
||||
/// </summary>
|
||||
public static string HTML_CUSTOM_INPUT = "customInput";
|
||||
//颜色选择器
|
||||
/// <summary>
|
||||
/// 颜色选择器
|
||||
/// </summary>
|
||||
public static string HTML_COLORPICKER = "colorPicker";
|
||||
//switch开关
|
||||
public static string HTML_SWITCH { get; set; }
|
||||
|
||||
/** 字符串类型 */
|
||||
public static string TYPE_STRING = "string";
|
||||
|
||||
/** 整型 */
|
||||
public static string TYPE_INT = "int";
|
||||
|
||||
/** 长整型 */
|
||||
public static string TYPE_LONG = "long";
|
||||
|
||||
/** 浮点型 */
|
||||
public static string TYPE_DOUBLE = "Double";
|
||||
|
||||
/** 时间类型 */
|
||||
public static string TYPE_DATE = "DateTime";
|
||||
|
||||
/** 模糊查询 */
|
||||
/// <summary>
|
||||
/// 模糊查询
|
||||
/// </summary>
|
||||
public static string QUERY_LIKE = "LIKE";
|
||||
|
||||
/** 需要 */
|
||||
/// <summary>
|
||||
/// 需要
|
||||
/// </summary>
|
||||
public static string REQUIRE = "1";
|
||||
/// <summary>
|
||||
/// 时间类型
|
||||
/// </summary>
|
||||
public static string TYPE_DATE = "DateTime";
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,10 @@ namespace ZR.CodeGenerator.Model
|
||||
/// vue代码路径
|
||||
/// </summary>
|
||||
public string VueParentPath { get; set; }
|
||||
/// <summary>
|
||||
/// uniapp存储路径
|
||||
/// </summary>
|
||||
public string AppVuePath { get; set; } = "ZRAdminn-app";
|
||||
#endregion
|
||||
public ReplaceDto ReplaceDto { get; set; }
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ namespace ZR.CodeGenerator.Model
|
||||
public bool ShowBtnView { get; set; }
|
||||
public bool ShowBtnTruncate { get; set; }
|
||||
public bool ShowBtnMultiDel { get; set; }
|
||||
public bool ShowBtnImport { get; set; }
|
||||
/// <summary>
|
||||
/// 上传URL data
|
||||
/// </summary>
|
||||
@ -69,5 +70,9 @@ namespace ZR.CodeGenerator.Model
|
||||
/// vue页面文件名
|
||||
/// </summary>
|
||||
public string ViewFileName { get; set; }
|
||||
/// <summary>
|
||||
/// 操作按钮样式
|
||||
/// </summary>
|
||||
public int OperBtnStyle { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Model;
|
||||
using SqlSugar;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -17,8 +18,7 @@ namespace ZR.CodeGenerator.Service
|
||||
{
|
||||
var db = GetSugarDbContext();
|
||||
//Oracle库特殊处理
|
||||
List<DbConfigs> dbConfigs = AppSettings.Get<List<DbConfigs>>("dbConfigs");
|
||||
DbConfigs configs = dbConfigs.Find(f => f.IsGenerateDb == true);
|
||||
DbConfigs configs = AppSettings.Get<DbConfigs>(nameof(GlobalConstant.CodeGenDbConfig));
|
||||
if (configs.DbType == 3)
|
||||
{
|
||||
return new List<string>() { configs?.DbName };
|
||||
|
||||
@ -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.84-preview10" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.105" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
ZR.Common/Model/WxTokenResult.cs
Normal file
13
ZR.Common/Model/WxTokenResult.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace ZR.Common.Model
|
||||
{
|
||||
public class WxTokenResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 0、正常
|
||||
/// </summary>
|
||||
public int errcode { get; set; }
|
||||
public string errmsg { get; set; }
|
||||
public string access_token { get; set; }
|
||||
public string ticket { get; set; }
|
||||
}
|
||||
}
|
||||
119
ZR.Common/WxHelper.cs
Normal file
119
ZR.Common/WxHelper.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ZR.Common.Model;
|
||||
|
||||
namespace ZR.Common
|
||||
{
|
||||
public class WxHelper
|
||||
{
|
||||
private static readonly string GetTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
|
||||
private static readonly string GetTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
|
||||
private static readonly string AppID = AppSettings.App(new string[] { "WxOpen", "AppID" });
|
||||
private static readonly string AppSECRET = AppSettings.App(new string[] { "WxOpen", "AppSecret" });
|
||||
|
||||
/// <summary>
|
||||
/// 获取访问token
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// {"errcode":0,"errmsg":"ok","access_token":"iCbcfE1OjfRhV0_io-CzqTNC0lnrudeW3oF5rhJKfmINaxLClLa1FoqAY_wEXtodYh_DTnrtAwZfzeb-NRXvwiOoqUTHx3i6QKLYcfBtF8y-xd5mvaeaf3e9mvTAPhmX0lkm1cLTwRLmoa1IwzgQ-QZEZcuIcntWdEMGseVYok3BwCGpC87bt6nNdgnekZdFVRp1uuaxoctDGlXpoQlQsA","expires_in":7200}
|
||||
/// </returns>
|
||||
private static WxTokenResult GetAccessToken()
|
||||
{
|
||||
if (AppID.IsEmpty() || AppSECRET.IsEmpty())
|
||||
{
|
||||
Console.WriteLine("公众号配置错误");
|
||||
throw new ArgumentException("公众号配置错误");
|
||||
};
|
||||
var Ck = "wx_token";
|
||||
string getTokenUrl = $"{GetTokenUrl}?grant_type=client_credential&appid={AppID}&secret={AppSECRET}";
|
||||
if (CacheHelper.Get(Ck) is WxTokenResult tokenResult)
|
||||
{
|
||||
return tokenResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
string result = HttpHelper.HttpGet(getTokenUrl);
|
||||
|
||||
tokenResult = JsonConvert.DeserializeObject<WxTokenResult>(result);
|
||||
|
||||
if (tokenResult?.errcode == 0)
|
||||
{
|
||||
CacheHelper.SetCache(Ck, tokenResult, 110);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("GetAccessToken失败,结果=" + result);
|
||||
throw new Exception("获取AccessToken失败");
|
||||
}
|
||||
}
|
||||
return tokenResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取ticket
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static WxTokenResult GetTicket()
|
||||
{
|
||||
WxTokenResult token = GetAccessToken();
|
||||
string ticket = token?.access_token;
|
||||
var Ck = "wx_ticket";
|
||||
string getTokenUrl = $"{GetTicketUrl}?access_token={ticket}&type=jsapi";
|
||||
if (CacheHelper.Get(Ck) is WxTokenResult tokenResult)
|
||||
{
|
||||
return tokenResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
string result = HttpHelper.HttpGet(getTokenUrl);
|
||||
tokenResult = JsonConvert.DeserializeObject<WxTokenResult>(result);
|
||||
|
||||
if (tokenResult?.errcode == 0)
|
||||
{
|
||||
CacheHelper.SetCache(Ck, tokenResult, 110);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("GetTicket,结果=" + result);
|
||||
throw new Exception("获取ticket失败");
|
||||
}
|
||||
}
|
||||
return tokenResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回正确的签名
|
||||
/// </summary>
|
||||
/// <param name="jsapi_ticket"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
/// <param name="noncestr"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetSignature(string jsapi_ticket, string timestamp, string noncestr, string url = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsapi_ticket) || string.IsNullOrEmpty(noncestr) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(url))
|
||||
return null;
|
||||
|
||||
//将字段添加到列表中。
|
||||
string[] arr = new[]
|
||||
{
|
||||
string.Format("jsapi_ticket={0}",jsapi_ticket),
|
||||
string.Format("noncestr={0}",noncestr),
|
||||
string.Format("timestamp={0}",timestamp),
|
||||
string.Format("url={0}",url)
|
||||
};
|
||||
//字典排序
|
||||
Array.Sort(arr);
|
||||
//使用URL键值对的格式拼接成字符串
|
||||
var temp = string.Join("&", arr);
|
||||
|
||||
var sha1Arr = SHA1.HashData(Encoding.UTF8.GetBytes(temp));
|
||||
|
||||
return BitConverter.ToString(sha1Arr).Replace("-", "").ToLower();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using Infrastructure;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using ZR.Common.Model;
|
||||
|
||||
namespace ZR.Common
|
||||
{
|
||||
@ -44,7 +45,7 @@ namespace ZR.Common
|
||||
System.Console.WriteLine("请完成企业微信配置");
|
||||
return (0, "请完成企业微信通知配置");
|
||||
}
|
||||
GetTokenResult tokenResult = GetAccessToken();
|
||||
WxTokenResult tokenResult = GetAccessToken();
|
||||
|
||||
if (tokenResult == null || tokenResult.errcode != 0)
|
||||
{
|
||||
@ -74,7 +75,7 @@ namespace ZR.Common
|
||||
//返回结果
|
||||
//{"errcode":0,"errmsg":"ok","invaliduser":""}
|
||||
string msgResult = HttpHelper.HttpPost(msgUrl, postData, "contentType/json");
|
||||
GetTokenResult getTokenResult = JsonSerializer.Deserialize<GetTokenResult>(msgResult);
|
||||
WxTokenResult getTokenResult = JsonSerializer.Deserialize<WxTokenResult>(msgResult);
|
||||
System.Console.WriteLine(msgResult);
|
||||
return (getTokenResult?.errcode == 0 ? 100 : 0, getTokenResult?.errmsg);
|
||||
}
|
||||
@ -89,12 +90,12 @@ namespace ZR.Common
|
||||
/// <returns>
|
||||
/// {"errcode":0,"errmsg":"ok","access_token":"iCbcfE1OjfRhV0_io-CzqTNC0lnrudeW3oF5rhJKfmINaxLClLa1FoqAY_wEXtodYh_DTnrtAwZfzeb-NRXvwiOoqUTHx3i6QKLYcfBtF8y-xd5mvaeaf3e9mvTAPhmX0lkm1cLTwRLmoa1IwzgQ-QZEZcuIcntWdEMGseVYok3BwCGpC87bt6nNdgnekZdFVRp1uuaxoctDGlXpoQlQsA","expires_in":7200}
|
||||
/// </returns>
|
||||
private static GetTokenResult GetAccessToken()
|
||||
private static WxTokenResult GetAccessToken()
|
||||
{
|
||||
string getTokenUrl = $"{GetTokenUrl}?corpid={CORPID}&corpsecret={CORPSECRET}";
|
||||
string getTokenResult = HttpHelper.HttpGet(getTokenUrl);
|
||||
System.Console.WriteLine(getTokenResult);
|
||||
GetTokenResult tokenResult = JsonSerializer.Deserialize<GetTokenResult>(getTokenResult);
|
||||
WxTokenResult tokenResult = JsonSerializer.Deserialize<WxTokenResult>(getTokenResult);
|
||||
return tokenResult;
|
||||
}
|
||||
|
||||
@ -146,15 +147,5 @@ namespace ZR.Common
|
||||
};
|
||||
return dic;
|
||||
}
|
||||
|
||||
public class GetTokenResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 0、正常
|
||||
/// </summary>
|
||||
public int errcode { get; set; }
|
||||
public string errmsg { get; set; }
|
||||
public string access_token { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.30.3" />
|
||||
<PackageReference Include="MailKit" Version="4.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\ZR.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
4
ZR.Model/GlobalUsing.cs
Normal file
4
ZR.Model/GlobalUsing.cs
Normal file
@ -0,0 +1,4 @@
|
||||
global using System.Collections.Generic;
|
||||
global using System;
|
||||
global using SqlSugar;
|
||||
global using Newtonsoft.Json;
|
||||
@ -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.30.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.84-preview10" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<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)
|
||||
{
|
||||
@ -56,15 +56,15 @@ namespace ZR.Repository
|
||||
}
|
||||
public IInsertable<T> Insertable(T t)
|
||||
{
|
||||
return Context.Insertable<T>(t);
|
||||
return Context.Insertable(t);
|
||||
}
|
||||
#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>
|
||||
///
|
||||
@ -212,13 +174,13 @@ namespace ZR.Repository
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public int Delete(object[] obj)
|
||||
public int Delete(object[] obj, string title = "")
|
||||
{
|
||||
return Context.Deleteable<T>().In(obj).ExecuteCommand();
|
||||
return Context.Deleteable<T>().In(obj).EnableDiffLogEventIF(title.IsNotEmpty(), title).ExecuteCommand();
|
||||
}
|
||||
public int Delete(object id)
|
||||
public int Delete(object id, string title = "")
|
||||
{
|
||||
return Context.Deleteable<T>(id).ExecuteCommand();
|
||||
return Context.Deleteable<T>(id).EnableDiffLogEventIF(title.IsNotEmpty(), title).ExecuteCommand();
|
||||
}
|
||||
public int DeleteTable()
|
||||
{
|
||||
@ -351,8 +313,12 @@ namespace ZR.Repository
|
||||
var total = 0;
|
||||
page.PageSize = parm.PageSize;
|
||||
page.PageIndex = parm.PageNum;
|
||||
|
||||
page.Result = source.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
|
||||
if (parm.Sort.IsNotEmpty())
|
||||
{
|
||||
source.OrderByPropertyName(parm.Sort, parm.SortType.Contains("desc") ? OrderByType.Desc : OrderByType.Asc);
|
||||
}
|
||||
page.Result = source
|
||||
//.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
|
||||
.ToPageList(parm.PageNum, parm.PageSize, ref total);
|
||||
page.TotalNum = total;
|
||||
return page;
|
||||
@ -372,11 +338,14 @@ namespace ZR.Repository
|
||||
var total = 0;
|
||||
page.PageSize = parm.PageSize;
|
||||
page.PageIndex = parm.PageNum;
|
||||
|
||||
if (parm.Sort.IsNotEmpty())
|
||||
{
|
||||
source.OrderByPropertyName(parm.Sort, parm.SortType.Contains("desc") ? OrderByType.Desc : OrderByType.Asc);
|
||||
}
|
||||
var result = source
|
||||
.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
|
||||
//.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
|
||||
.ToPageList(parm.PageNum, parm.PageSize, ref total);
|
||||
|
||||
|
||||
page.TotalNum = total;
|
||||
page.Result = result.Adapt<List<T2>>();
|
||||
return page;
|
||||
|
||||
@ -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);
|
||||
@ -47,8 +42,8 @@ namespace ZR.Repository
|
||||
|
||||
#region delete
|
||||
IDeleteable<T> Deleteable();
|
||||
int Delete(object[] obj);
|
||||
int Delete(object id);
|
||||
int Delete(object[] obj, string title = "");
|
||||
int Delete(object id, string title = "");
|
||||
int DeleteTable();
|
||||
bool Truncate();
|
||||
|
||||
|
||||
@ -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.84-preview10" />
|
||||
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.105" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user