diff --git a/.gitignore b/.gitignore index 34b14f9..be46788 100644 --- a/.gitignore +++ b/.gitignore @@ -259,7 +259,11 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc -/ZRAdmin/Properties/launchSettings.json -/ZRAdmin/Properties/PublishProfiles /ZR.Admin.WebApi/appsettings.Stage.json /CodeGenerate +/ZR.Admin.WebApi/appsettings.Production.json +/ZR.Admin.WebApi/wwwroot/uploads +/ZR.Admin.WebApi/wwwroot/Generatecode +/ZR.Admin.WebApi/wwwroot/export +/ZR.Vue/src/views/business/Gendemo.vue +/ZR.Admin.WebApi/Properties/launchSettings.json diff --git a/Infrastructure/ConfigUtils.cs b/Infrastructure/ConfigUtils.cs index 617875d..c733a9e 100644 --- a/Infrastructure/ConfigUtils.cs +++ b/Infrastructure/ConfigUtils.cs @@ -14,7 +14,7 @@ namespace Infrastructure static ConfigUtils() { - Config = App.ServiceProvider.GetRequiredService(); + Configuration = App.ServiceProvider.GetRequiredService(); if (Instance == null) Instance = new ConfigUtils(); @@ -22,35 +22,22 @@ namespace Infrastructure public static ConfigUtils Instance { get; private set; } #endregion - - private static IConfiguration Config { get; set; } - - /// - /// 泛型读取配置文件 - /// 目前还不能绑定到实体类 - /// - /// 获取不到配置文件设定默认值 - /// 要获取的配置文件节点名称 - /// - //public T GetConfig(string key, T defaultValue = default) - //{ - // //GetValue扩展包需要安装Microsoft.Extensions.Configuration - // var setting = Config.GetValue(key, defaultValue); - - // Console.WriteLine($"获取配置文件值key={key},value={setting}"); - // return setting; - //} + private static IConfiguration Configuration { get; set; } public T GetAppConfig(string key, T defaultValue = default(T)) { - T setting = (T)Convert.ChangeType(Config[key], typeof(T)); + T setting = (T)Convert.ChangeType(Configuration[key], typeof(T)); var value = setting; if (setting == null) value = defaultValue; - //Console.WriteLine($"获取配置文件值key={key},value={value}"); return value; } - + public T Bind(string key, T t) + { + Configuration.Bind(key, t); + + return t; + } /// /// 获取配置文件 /// @@ -58,7 +45,7 @@ namespace Infrastructure /// public string GetConfig(string key) { - return Config[key]; + return Configuration[key]; } /// @@ -66,10 +53,9 @@ namespace Infrastructure /// /// /// - public string GetConnectionStrings(string key) + public string GetConnectionString(string key) { - return Config.GetConnectionString(key); - + return Configuration.GetConnectionString(key); } } } diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj index d878cb3..2884497 100644 --- a/Infrastructure/Infrastructure.csproj +++ b/Infrastructure/Infrastructure.csproj @@ -4,6 +4,10 @@ net5.0 + + + + diff --git a/Infrastructure/OptionsSetting.cs b/Infrastructure/OptionsSetting.cs index 7833a53..dc36620 100644 --- a/Infrastructure/OptionsSetting.cs +++ b/Infrastructure/OptionsSetting.cs @@ -50,4 +50,27 @@ namespace Infrastructure public string KEY { get; set; } public string SECRET { get; set; } } + + /// + /// Jwt + /// + public class JwtSettings + { + /// + /// token是谁颁发的 + /// + public string Issuer { get; set; } + /// + /// token可以给那些客户端使用 + /// + public string Audience { get; set; } + /// + /// 加密的key(SecretKey必须大于16个,是大于,不是大于等于) + /// + public string SecretKey { get; set; } + /// + /// token时间(分) + /// + public int Expire { get; set; } = 1440; + } } diff --git a/ZR.Admin.WebApi/Controllers/BaseController.cs b/ZR.Admin.WebApi/Controllers/BaseController.cs index f19cc41..b34e50e 100644 --- a/ZR.Admin.WebApi/Controllers/BaseController.cs +++ b/ZR.Admin.WebApi/Controllers/BaseController.cs @@ -9,6 +9,8 @@ using OfficeOpenXml; using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Reflection; using ZR.Admin.WebApi.Filters; namespace ZR.Admin.WebApi.Controllers @@ -120,13 +122,13 @@ namespace ZR.Admin.WebApi.Controllers //调试模式需要加上 ExcelPackage.LicenseContext = LicenseContext.NonCommercial; Directory.CreateDirectory(Path.GetDirectoryName(newFileName)); - using (ExcelPackage package = new ExcelPackage(new FileInfo(newFileName))) + using (ExcelPackage package = new(new FileInfo(newFileName))) { // 添加worksheet ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(sheetName); //全部字段导出 - worksheet.Cells.LoadFromCollection(list, true); + worksheet.Cells.LoadFromCollection(list, true, OfficeOpenXml.Table.TableStyles.Light13); package.Save(); } diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs new file mode 100644 index 0000000..591d78f --- /dev/null +++ b/ZR.Admin.WebApi/Controllers/CommonController.cs @@ -0,0 +1,135 @@ +using Infrastructure; +using Infrastructure.Attribute; +using Infrastructure.Model; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System; +using System.IO; +using System.Linq; +using ZR.Admin.WebApi.Filters; +using ZR.Common; +using ZR.Service.System.IService; + +namespace ZR.Admin.WebApi.Controllers +{ + /// + /// 公共模块 + /// + [Route("[controller]/[action]")] + public class CommonController : BaseController + { + private OptionsSetting OptionsSetting; + private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + private IWebHostEnvironment WebHostEnvironment; + private ISysFileService SysFileService; + public CommonController(IOptions options, IWebHostEnvironment webHostEnvironment, ISysFileService fileService) + { + WebHostEnvironment = webHostEnvironment; + SysFileService = fileService; + OptionsSetting = options.Value; + } + + /// + /// 心跳 + /// + /// + [HttpGet, Route("health/index")] + public IActionResult Health() + { + return SUCCESS(true); + } + + /// + /// 发送邮件 + /// + /// 请求参数接收实体 + /// + [ActionPermissionFilter(Permission = "tool:email:send")] + [Log(Title = "发送邮件", IsSaveRequestData = false)] + [HttpPost] + public IActionResult SendEmail([FromBody] SendEmailDto sendEmailVo) + { + if (sendEmailVo == null || string.IsNullOrEmpty(sendEmailVo.Subject) || string.IsNullOrEmpty(sendEmailVo.ToUser)) + { + return ToResponse(ApiResult.Error($"请求参数不完整")); + } + if (string.IsNullOrEmpty(OptionsSetting.MailOptions.From) || string.IsNullOrEmpty(OptionsSetting.MailOptions.Password)) + { + return ToResponse(ApiResult.Error($"请配置邮箱信息")); + } + MailHelper mailHelper = new MailHelper(OptionsSetting.MailOptions.From, OptionsSetting.MailOptions.Smtp, OptionsSetting.MailOptions.Port, OptionsSetting.MailOptions.Password); + + mailHelper.SendMail(sendEmailVo.ToUser, sendEmailVo.Subject, sendEmailVo.Content, sendEmailVo.FileUrl, sendEmailVo.HtmlContent); + + logger.Info($"发送邮件{JsonConvert.SerializeObject(sendEmailVo)}"); + + return SUCCESS(true); + } + + #region 上传 + + /// + /// 存储文件 + /// + /// + /// + [HttpPost()] + [Verify] + [ActionPermissionFilter(Permission = "system")] + public IActionResult UploadFile([FromForm(Name = "file")] IFormFile formFile) + { + if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传图片不能为空"); + string fileExt = Path.GetExtension(formFile.FileName); + string fileName = FileUtil.HashFileName(Guid.NewGuid().ToString()).ToLower() + fileExt; + string finalFilePath = Path.Combine(WebHostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads"), fileName); + finalFilePath = finalFilePath.Replace("\\", "/").Replace("//", "/"); + + if (!Directory.Exists(Path.GetDirectoryName(finalFilePath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(finalFilePath)); + } + + using (var stream = new FileStream(finalFilePath, FileMode.Create)) + { + formFile.CopyTo(stream); + } + + string accessPath = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads").Replace("\\", " /")}{fileName}"; + return ToResponse(ResultCode.SUCCESS, accessPath); + } + + /// + /// 存储文件到阿里云 + /// + /// + /// + [HttpPost] + [Verify] + [ActionPermissionFilter(Permission = "system")] + public IActionResult UploadFileAliyun([FromForm(Name = "file")] IFormFile formFile) + { + if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空"); + string fileExt = Path.GetExtension(formFile.FileName); + string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".jpeg", ".webp", ".svga", ".xls" }; + int MaxContentLength = 1024 * 1024 * 4; + + if (!AllowedFileExtensions.Contains(fileExt)) + { + return ToResponse(ResultCode.CUSTOM_ERROR, "上传失败,未经允许上传类型"); + } + + if (formFile.Length > MaxContentLength) + { + return ToResponse(ResultCode.CUSTOM_ERROR, "上传文件过大,不能超过 " + (MaxContentLength / 1024).ToString() + " MB"); + } + (bool, string) result = SysFileService.SaveFile("", formFile); + + return ToResponse(ResultCode.SUCCESS, result.Item2); + } + #endregion + } +} diff --git a/ZR.Admin.WebApi/Controllers/HomeController.cs b/ZR.Admin.WebApi/Controllers/HomeController.cs deleted file mode 100644 index c670ea5..0000000 --- a/ZR.Admin.WebApi/Controllers/HomeController.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Infrastructure; -using Infrastructure.Attribute; -using Infrastructure.Model; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System; -using ZR.Admin.WebApi.Filters; -using ZR.Common; - -namespace ZR.Admin.WebApi.Controllers -{ - public class HomeController : BaseController - { - private OptionsSetting OptionsSetting; - private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - public HomeController(IOptions options) - { - OptionsSetting = options.Value; - } - - /// - /// 心跳 - /// - /// - [HttpGet, Route("health/index")] - [Log()] - public IActionResult Health() - { - return SUCCESS(true); - } - - /// - /// 加密 - /// - /// - /// - public IActionResult Encrypt(string content) - { - if (string.IsNullOrEmpty(content)) - { - throw new Exception("content不能为空"); - } - string key = ConfigUtils.Instance.GetConfig("DbKey"); - string encryptTxt = NETCore.Encrypt.EncryptProvider.DESEncrypt(content, key); - return Ok(new { content, encryptTxt }); - } - - /// - /// 解密 - /// - /// - /// - public IActionResult Decrypt(string content) - { - if (string.IsNullOrEmpty(content)) - { - throw new Exception("content不能为空"); - } - string key = ConfigUtils.Instance.GetConfig("DbKey"); - string encryptTxt = NETCore.Encrypt.EncryptProvider.DESDecrypt(content, key); - return Ok(new { content, encryptTxt }); - } - - /// - /// 发送邮件 - /// - /// 请求参数接收实体 - /// - [ActionPermissionFilter(Permission = "tool:email:send")] - public IActionResult SendEmail([FromBody] SendEmailDto sendEmailVo) - { - if (sendEmailVo == null || string.IsNullOrEmpty(sendEmailVo.Subject) || string.IsNullOrEmpty(sendEmailVo.ToUser)) - { - return ToResponse(ApiResult.Error($"请求参数不完整")); - } - if (string.IsNullOrEmpty(OptionsSetting.MailOptions.From) || string.IsNullOrEmpty(OptionsSetting.MailOptions.Password)) - { - return ToResponse(ApiResult.Error($"请配置邮箱信息")); - } - MailHelper mailHelper = new MailHelper(OptionsSetting.MailOptions.From, OptionsSetting.MailOptions.Smtp, OptionsSetting.MailOptions.Port, OptionsSetting.MailOptions.Password); - - mailHelper.SendMail(sendEmailVo.ToUser, sendEmailVo.Subject, sendEmailVo.Content, sendEmailVo.FileUrl, sendEmailVo.HtmlContent); - - logger.Info($"发送邮件{JsonConvert.SerializeObject(sendEmailVo)}"); - - return SUCCESS(true); - } - } -} diff --git a/ZR.Admin.WebApi/Controllers/System/ArticleController.cs b/ZR.Admin.WebApi/Controllers/System/ArticleController.cs index 0466f31..6c993d3 100644 --- a/ZR.Admin.WebApi/Controllers/System/ArticleController.cs +++ b/ZR.Admin.WebApi/Controllers/System/ArticleController.cs @@ -49,7 +49,7 @@ namespace ZR.Admin.WebApi.Controllers predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.Title), m => m.Title.Contains(parm.Title)); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.Status), m => m.Status == parm.Status); - var response = _ArticleService.GetPages(predicate.ToExpression(), parm, f => f.Cid, "Desc"); + var response = _ArticleService.GetPages(predicate.ToExpression(), parm, f => f.Cid, OrderByType.Desc); return SUCCESS(response); } diff --git a/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs b/ZR.Admin.WebApi/Controllers/System/CodeGeneratorController.cs similarity index 87% rename from ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs rename to ZR.Admin.WebApi/Controllers/System/CodeGeneratorController.cs index e503f8e..61fc996 100644 --- a/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs +++ b/ZR.Admin.WebApi/Controllers/System/CodeGeneratorController.cs @@ -19,7 +19,7 @@ using ZR.Common; using ZR.Model; using ZR.Model.System.Dto; using ZR.Model.System.Generate; -using ZR.Model.Vo; +using ZR.Service; using ZR.Service.System.IService; namespace ZR.Admin.WebApi.Controllers @@ -27,17 +27,24 @@ namespace ZR.Admin.WebApi.Controllers /// /// 代码生成 /// + [Verify] [Route("tool/gen")] public class CodeGeneratorController : BaseController { private CodeGeneraterService _CodeGeneraterService = new CodeGeneraterService(); private IGenTableService GenTableService; private IGenTableColumnService GenTableColumnService; + private readonly ISysDictDataService SysDictDataService; private IWebHostEnvironment WebHostEnvironment; - public CodeGeneratorController(IGenTableService genTableService, IGenTableColumnService genTableColumnService, IWebHostEnvironment webHostEnvironment) + public CodeGeneratorController( + IGenTableService genTableService, + IGenTableColumnService genTableColumnService, + ISysDictDataService dictDataService, + IWebHostEnvironment webHostEnvironment) { GenTableService = genTableService; GenTableColumnService = genTableColumnService; + SysDictDataService = dictDataService; WebHostEnvironment = webHostEnvironment; } @@ -66,43 +73,8 @@ namespace ZR.Admin.WebApi.Controllers public IActionResult FindListTable(string dbName, string tableName, PagerInfo pager) { List list = _CodeGeneraterService.GetAllTables(dbName, tableName, pager); - var vm = new VMPageResult(list, pager); - return SUCCESS(vm); - } - - /// - /// 代码生成器 - /// - /// 数据传输对象 - /// - [HttpPost("genCode")] - [Log(Title = "代码生成", BusinessType = BusinessType.GENCODE)] - [ActionPermissionFilter(Permission = "tool:gen:code")] - public IActionResult Generate([FromBody] GenerateDto dto) - { - if (dto.TableId <= 0) - { - throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空"); - } - dto.ZipPath = Path.Combine(WebHostEnvironment.WebRootPath, "Generatecode"); - dto.GenCodePath = Path.Combine(dto.ZipPath, DateTime.Now.ToString("yyyyMMdd")); - - var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId); - genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId); - if (!string.IsNullOrEmpty(genTableInfo.Options)) - { - Dictionary options = JsonConvert.DeserializeObject>(genTableInfo.Options); - dto.ParentMenuId = (long)options.GetValueOrDefault("parentMenuId", 0); - } - dto.GenTable = genTableInfo; - //生成代码 - CodeGeneratorTool.Generate(genTableInfo, dto); - //下载文件 - FileHelper.ZipGenCode(dto); - - //HttpContext.Response.Headers.Add("Content-disposition", $"attachment; filename={zipFileName}"); - return SUCCESS(new { zipPath = "/Generatecode/" + dto.ZipFileName, fileName = dto.ZipFileName }); + return SUCCESS(list.ToPage(pager)); } /// @@ -130,7 +102,7 @@ namespace ZR.Admin.WebApi.Controllers { var tableColumns = GenTableColumnService.GenTableColumns(tableId); var tableInfo = GenTableService.GetGenTableInfo(tableId); - return SUCCESS(new { result = tableColumns, info = tableInfo }); + return SUCCESS(new { cloumns = tableColumns, info = tableInfo }); } /// @@ -177,11 +149,11 @@ namespace ZR.Admin.WebApi.Controllers BaseNameSpace = "ZR.",//导入默认命名空间前缀 ModuleName = "business",//导入默认模块名 ClassName = CodeGeneratorTool.GetClassName(tableName), - BusinessName = CodeGeneratorTool.GetClassName(tableName), + BusinessName = CodeGeneratorTool.GetBusinessName(tableName), FunctionAuthor = ConfigUtils.Instance.GetConfig(GenConstants.Gen_author), - FunctionName = string.IsNullOrEmpty(tabInfo.Description) ? tableName : tabInfo.Description, TableName = tableName, - TableComment = string.IsNullOrEmpty(tabInfo.Description) ? tableName : tabInfo.Description, + TableComment = tabInfo?.Description, + FunctionName = tabInfo?.Description, Create_by = userName, }; genTable.TableId = GenTableService.ImportGenTable(genTable); @@ -217,7 +189,12 @@ namespace ZR.Admin.WebApi.Controllers if (genTableDto == null) throw new CustomException("请求参数错误"); var genTable = genTableDto.Adapt().ToUpdate(HttpContext); - genTable.Options = JsonConvert.SerializeObject(new { parentMenuId = genTableDto.ParentMenuId }); + genTable.Options = JsonConvert.SerializeObject(new + { + parentMenuId = genTableDto.ParentMenuId, + sortField = genTableDto.SortField, + sortType = genTable.SortType + }); int rows = GenTableService.UpdateGenTable(genTable); if (rows > 0) { @@ -241,16 +218,52 @@ namespace ZR.Admin.WebApi.Controllers } var genTableInfo = GenTableService.GetGenTableInfo(tableId); genTableInfo.Columns = GenTableColumnService.GenTableColumns(tableId); + + //var dictList = genTableInfo.Columns.FindAll(x => !string.IsNullOrEmpty(x.DictType)); + //foreach (var item in dictList) + //{ + // item.DictDatas = SysDictDataService.SelectDictDataByType(item.DictType); + //} GenerateDto dto = new(); dto.GenTable = genTableInfo; dto.ZipPath = Path.Combine(WebHostEnvironment.WebRootPath, "Generatecode"); dto.GenCodePath = Path.Combine(dto.ZipPath, DateTime.Now.ToString("yyyyMMdd")); dto.IsPreview = 1; - dto.GenCodeFiles = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }; //生成代码 - CodeGeneratorTool.Generate(genTableInfo, dto); + CodeGeneratorTool.Generate(dto); return SUCCESS(dto.GenCodes); } + + /// + /// 生成代码(下载方式) + /// + /// 数据传输对象 + /// + [HttpPost("genCode")] + [Log(Title = "代码生成", BusinessType = BusinessType.GENCODE)] + [ActionPermissionFilter(Permission = "tool:gen:code")] + public IActionResult Generate([FromBody] GenerateDto dto) + { + if (dto.TableId <= 0) + { + throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空"); + } + dto.ZipPath = Path.Combine(WebHostEnvironment.WebRootPath, "Generatecode"); + dto.GenCodePath = Path.Combine(dto.ZipPath, DateTime.Now.ToString("yyyyMMdd")); + + var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId); + genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId); + + dto.GenTable = genTableInfo; + //生成代码 + CodeGeneratorTool.Generate(dto); + //下载文件 + FileHelper.ZipGenCode(dto); + + //HttpContext.Response.Headers.Add("Content-disposition", $"attachment; filename={zipFileName}"); + return SUCCESS(new { zipPath = "/Generatecode/" + dto.ZipFileName, fileName = dto.ZipFileName }); + } + } } diff --git a/ZR.Admin.WebApi/Controllers/System/SysConfigController.cs b/ZR.Admin.WebApi/Controllers/System/SysConfigController.cs index 55425f6..5e47b9d 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysConfigController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysConfigController.cs @@ -9,14 +9,13 @@ using Infrastructure.Enums; using Infrastructure.Model; using Mapster; using ZR.Model.Dto; -using ZR.Model.Models; -using ZR.Service.Business; using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Filters; using ZR.Common; using ZR.Service.System; using ZR.Model.System; using Infrastructure.Extensions; +using Microsoft.AspNetCore.Authorization; namespace ZR.Admin.WebApi.Controllers { @@ -83,6 +82,7 @@ namespace ZR.Admin.WebApi.Controllers /// /// [HttpGet("configKey/{configKey}")] + [AllowAnonymous] public IActionResult GetConfigKey(string configKey) { //TODO 增加缓存 @@ -107,7 +107,7 @@ namespace ZR.Admin.WebApi.Controllers //从 Dto 映射到 实体 var model = parm.Adapt().ToCreate(); - return SUCCESS(_SysConfigService.Add(model, it => new + return SUCCESS(_SysConfigService.Insert(model, it => new { it.ConfigName, it.ConfigKey, @@ -144,6 +144,7 @@ namespace ZR.Admin.WebApi.Controllers ConfigType = model.ConfigType, Update_by = model.Update_by, Update_time = model.Update_time, + Remark = model.Remark }); return SUCCESS(response); diff --git a/ZR.Admin.WebApi/Controllers/System/SysDictDataController.cs b/ZR.Admin.WebApi/Controllers/System/SysDictDataController.cs index c5fe262..86e178b 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysDictDataController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysDictDataController.cs @@ -38,10 +38,8 @@ namespace ZR.Admin.WebApi.Controllers.System [HttpGet("list")] public IActionResult List([FromQuery] SysDictData dictData, [FromQuery] PagerInfo pagerInfo) { - var list = SysDictDataService.SelectDictDataList(dictData); - pagerInfo.TotalNum = list.Count; - var vm = new VMPageResult(list, pagerInfo); - return SUCCESS(vm); + var list = SysDictDataService.SelectDictDataList(dictData, pagerInfo); + return SUCCESS(list); } /// @@ -107,7 +105,7 @@ namespace ZR.Admin.WebApi.Controllers.System [HttpDelete("{dictCode}")] public IActionResult Remove(string dictCode) { - long[] dictCodes = ZR.Common.Tools.SpitLongArrary(dictCode); + long[] dictCodes = Common.Tools.SpitLongArrary(dictCode); return SUCCESS(SysDictDataService.DeleteDictDataByIds(dictCodes)); } diff --git a/ZR.Admin.WebApi/Controllers/System/SysDictTypeController.cs b/ZR.Admin.WebApi/Controllers/System/SysDictTypeController.cs index 7efaf3f..1e66890 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysDictTypeController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysDictTypeController.cs @@ -38,8 +38,7 @@ namespace ZR.Admin.WebApi.Controllers.System { var list = SysDictService.SelectDictTypeList(dict, pagerInfo); - var vm = new VMPageResult(list, pagerInfo); - return SUCCESS(vm, TIME_FORMAT_FULL); + return SUCCESS(list, TIME_FORMAT_FULL); } /// diff --git a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs index 13cfd24..6687616 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs @@ -15,6 +15,7 @@ using ZR.Model.System.Dto; using ZR.Service.System.IService; using Hei.Captcha; using ZR.Common; +using ZR.Service.System; namespace ZR.Admin.WebApi.Controllers.System { @@ -30,6 +31,7 @@ namespace ZR.Admin.WebApi.Controllers.System private readonly ISysLoginService sysLoginService; private readonly ISysPermissionService permissionService; private readonly SecurityCodeHelper SecurityCodeHelper; + private readonly ISysConfigService sysConfigService; public SysLoginController( IHttpContextAccessor contextAccessor, @@ -37,6 +39,7 @@ namespace ZR.Admin.WebApi.Controllers.System ISysUserService sysUserService, ISysLoginService sysLoginService, ISysPermissionService permissionService, + ISysConfigService configService, SecurityCodeHelper captcha) { httpContextAccessor = contextAccessor; @@ -45,6 +48,7 @@ namespace ZR.Admin.WebApi.Controllers.System this.sysUserService = sysUserService; this.sysLoginService = sysLoginService; this.permissionService = permissionService; + this.sysConfigService = configService; } @@ -60,7 +64,8 @@ namespace ZR.Admin.WebApi.Controllers.System { if (loginBody == null) { throw new CustomException("请求参数错误"); } loginBody.LoginIP = HttpContextExtension.GetClientUserIp(HttpContext); - if (CacheHelper.Get(loginBody.Uuid) is string str && !str.ToLower().Equals(loginBody.Code.ToLower())) + SysConfig sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff"); + if (sysConfig?.ConfigValue != "off" && CacheHelper.Get(loginBody.Uuid) is string str && !str.ToLower().Equals(loginBody.Code.ToLower())) { throw new CustomException(ResultCode.CAPTCHA_ERROR, "验证码错误"); } @@ -74,7 +79,7 @@ namespace ZR.Admin.WebApi.Controllers.System #endregion LoginUser loginUser = new LoginUser(user.UserId, user.UserName, roles, permissions); - return SUCCESS(JwtUtil.GenerateJwtToken(HttpContext.WriteCookies(loginUser))); + return SUCCESS(JwtUtil.GenerateJwtToken(HttpContext.AddClaims(loginUser))); } /// @@ -85,11 +90,11 @@ namespace ZR.Admin.WebApi.Controllers.System [HttpPost("logout")] public IActionResult LogOut() { - Task.Run(async () => - { - //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut - await HttpContext.SignOutAsync(); - }).Wait(); + //Task.Run(async () => + //{ + // //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut + // await HttpContext.SignOutAsync(); + //}).Wait(); return SUCCESS(1); } @@ -136,8 +141,26 @@ namespace ZR.Admin.WebApi.Controllers.System public ApiResult CaptchaImage() { string uuid = Guid.NewGuid().ToString().Replace("-", ""); + + SysConfig sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff"); var code = SecurityCodeHelper.GetRandomEnDigitalText(4); - var imgByte = SecurityCodeHelper.GetEnDigitalCodeByte(code); + byte[] imgByte; + if (sysConfig.ConfigValue == "1") + { + imgByte = SecurityCodeHelper.GetGifEnDigitalCodeByte(code);//动态gif数字字母 + } + else if (sysConfig.ConfigValue == "2") + { + imgByte = SecurityCodeHelper.GetGifBubbleCodeByte(code);//动态gif泡泡 + } + else if (sysConfig.ConfigValue == "3") + { + imgByte = SecurityCodeHelper.GetBubbleCodeByte(code);//泡泡 + } + else + { + imgByte = SecurityCodeHelper.GetEnDigitalCodeByte(code);//英文字母加数字 + } string base64Str = Convert.ToBase64String(imgByte); CacheHelper.SetCache(uuid, code); var obj = new { uuid, img = base64Str };// File(stream, "image/png") diff --git a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs index 274bd54..bb310ac 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs @@ -120,6 +120,7 @@ namespace ZR.Admin.WebApi.Controllers.System /// /// 修改头像 /// + /// /// [HttpPost("Avatar")] [ActionPermissionFilter(Permission = "system")] @@ -131,7 +132,7 @@ namespace ZR.Admin.WebApi.Controllers.System if (formFile == null) throw new CustomException("请选择文件"); string fileExt = Path.GetExtension(formFile.FileName); - string savePath = Path.Combine("wwwroot", FileUtil.GetdirPath("uploads")); + string savePath = Path.Combine(hostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads")); Console.WriteLine(savePath); if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } @@ -141,7 +142,7 @@ namespace ZR.Admin.WebApi.Controllers.System using (var stream = new FileStream(finalFilePath, FileMode.Create)) { - formFile.CopyToAsync(stream); + formFile.CopyTo(stream); } string accessUrl = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads")}{fileName}"; diff --git a/ZR.Admin.WebApi/Controllers/System/SysUserController.cs b/ZR.Admin.WebApi/Controllers/System/SysUserController.cs index 9d333f6..fd2242e 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysUserController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysUserController.cs @@ -11,7 +11,7 @@ using System.IO; using ZR.Admin.WebApi.Filters; using ZR.Model; using ZR.Model.System; -using ZR.Model.Vo; +using ZR.Service; using ZR.Service.System.IService; namespace ZR.Admin.WebApi.Controllers.System @@ -53,9 +53,7 @@ namespace ZR.Admin.WebApi.Controllers.System { var list = UserService.SelectUserList(user, pager); - var vm = new VMPageResult(list, pager); - - return SUCCESS(vm, TIME_FORMAT_FULL); + return SUCCESS(list.ToPage(pager), TIME_FORMAT_FULL); } /// @@ -220,48 +218,10 @@ namespace ZR.Admin.WebApi.Controllers.System [ActionPermissionFilter(Permission = "system:user:export")] public IActionResult UserExport([FromQuery] SysUser user) { - string sFileName = $"用户列表{DateTime.Now:yyyyMMddHHmmss}.xlsx"; - string newFileName = Path.Combine(WebHostEnvironment.WebRootPath, "export", sFileName); var list = UserService.SelectUserList(user, new PagerInfo(1, 10000)); //调试模式需要加上 - ExcelPackage.LicenseContext = LicenseContext.NonCommercial; - Directory.CreateDirectory(Path.GetDirectoryName(newFileName)); - using (ExcelPackage package = new ExcelPackage(new FileInfo(newFileName))) - { - // 添加worksheet - ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("sysuser"); - #region 自定义导出 - //添加头 - //worksheet.Cells[1, 1].Value = "用户id"; - //worksheet.Cells[1, 2].Value = "用户名称"; - //worksheet.Cells[1, 3].Value = "用户昵称"; - //worksheet.Cells[1, 4].Value = "部门"; - //worksheet.Cells[1, 5].Value = "手机号码"; - //worksheet.Cells[1, 6].Value = "性别"; - //worksheet.Cells[1, 7].Value = "状态"; - //worksheet.Cells[1, 8].Value = "添加时间"; - //worksheet.Cells[1, 9].Value = "登录IP"; - //worksheet.Cells[1, 10].Value = "最后登录时间"; - //for (int i = 0; i < list.Count; i++) - //{ - // var item = list[i]; - // //worksheet.Cells[i + 2, 1].Value = item.UserId; - // //worksheet.Cells[i + 2, 2].Value = item.UserName; - // //worksheet.Cells[i + 2, 3].Value = item.NickName; - // //worksheet.Cells[i + 2, 4].Value = item.DeptName; - // //worksheet.Cells[i + 2, 5].Value = item.Phonenumber; - // //worksheet.Cells[i + 2, 6].Value = item.Sex; - // //worksheet.Cells[i + 2, 7].Value = item.Status; - // //worksheet.Cells[i + 2, 8].Value = item.Create_time.ToString(); - // //worksheet.Cells[i + 2, 9].Value = item.LoginIP; - // //worksheet.Cells[i + 2, 10].Value = item.LoginDate.ToString(); - //} - #endregion - //全部字段导出 - worksheet.Cells.LoadFromCollection(list, true); - package.Save(); - } + string sFileName = ExportExcel(list, "user", "用户列表"); return SUCCESS(new { path = "/export/" + sFileName, fileName = sFileName }); } } diff --git a/ZR.Admin.WebApi/Controllers/System/TasksController.cs b/ZR.Admin.WebApi/Controllers/System/TasksController.cs index 4ec1e09..d2d8148 100644 --- a/ZR.Admin.WebApi/Controllers/System/TasksController.cs +++ b/ZR.Admin.WebApi/Controllers/System/TasksController.cs @@ -20,7 +20,7 @@ namespace ZR.Admin.WebApi.Controllers /// /// 计划任务 /// - //[Verify] + [Verify] [Route("system/Tasks")] public class TasksController : BaseController { @@ -51,7 +51,7 @@ namespace ZR.Admin.WebApi.Controllers m.JobGroup.Contains(parm.QueryText) || m.AssemblyName.Contains(parm.QueryText)); - var response = _tasksQzService.GetPages(predicate.ToExpression(), pager, f => f.IsStart, "Desc"); + var response = _tasksQzService.GetPages(predicate.ToExpression(), pager, f => f.IsStart, OrderByType.Desc); return SUCCESS(response, TIME_FORMAT_FULL); } diff --git a/ZR.Admin.WebApi/Controllers/System/TasksLogController.cs b/ZR.Admin.WebApi/Controllers/System/TasksLogController.cs index 3ce61dd..867ba3d 100644 --- a/ZR.Admin.WebApi/Controllers/System/TasksLogController.cs +++ b/ZR.Admin.WebApi/Controllers/System/TasksLogController.cs @@ -13,6 +13,7 @@ using Infrastructure; namespace ZR.Admin.WebApi.Controllers.System { + [Verify] [Route("/monitor/jobLog")] public class TasksLogController : BaseController { @@ -42,7 +43,7 @@ namespace ZR.Admin.WebApi.Controllers.System predicate = predicate.AndIF(queryDto.Status.IfNotEmpty(), m => m.Status == queryDto.Status); predicate = predicate.AndIF(queryDto.JobId.IfNotEmpty(), m => m.JobId == queryDto.JobId); - var response = tasksLogService.GetPages(predicate.ToExpression(), pager, m => m.CreateTime, "Desc"); + var response = tasksLogService.GetPages(predicate.ToExpression(), pager, m => m.CreateTime, OrderByType.Desc); return SUCCESS(response, TIME_FORMAT_FULL); } diff --git a/ZR.Admin.WebApi/Controllers/System/monitor/SysLogininforController.cs b/ZR.Admin.WebApi/Controllers/System/monitor/SysLogininforController.cs index 38be60d..84c1513 100644 --- a/ZR.Admin.WebApi/Controllers/System/monitor/SysLogininforController.cs +++ b/ZR.Admin.WebApi/Controllers/System/monitor/SysLogininforController.cs @@ -38,9 +38,8 @@ namespace ZR.Admin.WebApi.Controllers.monitor public IActionResult LoignLogList([FromQuery] SysLogininfor sysLogininfoDto, [FromQuery] PagerInfo pagerInfo) { var list = sysLoginService.GetLoginLog(sysLogininfoDto, pagerInfo); - var vMPage = new VMPageResult(list, pagerInfo); - return ToResponse(ToJson(vMPage.TotalNum, vMPage), TIME_FORMAT_FULL_2); + return ToResponse(ToJson(list.Count, list.ToPage(pagerInfo)), TIME_FORMAT_FULL_2); } /// diff --git a/ZR.Admin.WebApi/Controllers/System/monitor/SysOperlogController.cs b/ZR.Admin.WebApi/Controllers/System/monitor/SysOperlogController.cs index 09ecf62..abefe0f 100644 --- a/ZR.Admin.WebApi/Controllers/System/monitor/SysOperlogController.cs +++ b/ZR.Admin.WebApi/Controllers/System/monitor/SysOperlogController.cs @@ -41,9 +41,8 @@ namespace ZR.Admin.WebApi.Controllers.monitor PagerInfo pagerInfo = new PagerInfo(sysOperLog.pageNum); var list = sysOperLogService.SelectOperLogList(sysOperLog, pagerInfo); - var vMPage = new VMPageResult(list, pagerInfo); - return ToResponse(ToJson(vMPage.TotalNum, vMPage), TIME_FORMAT_FULL_2); + return ToResponse(ToJson(list.TotalNum, list), TIME_FORMAT_FULL_2); } /// @@ -84,7 +83,7 @@ namespace ZR.Admin.WebApi.Controllers.monitor public IActionResult Export([FromQuery] SysOperLogDto sysOperLog) { var list = sysOperLogService.SelectOperLogList(sysOperLog, new PagerInfo(1, 10000)); - string sFileName = ExportExcel(list, "operlog", "操作日志"); + string sFileName = ExportExcel(list.Result, "operlog", "操作日志"); return SUCCESS(new { path = "/export/" + sFileName, fileName = sFileName }); } diff --git a/ZR.Admin.WebApi/Controllers/UploadController.cs b/ZR.Admin.WebApi/Controllers/UploadController.cs deleted file mode 100644 index f1dece4..0000000 --- a/ZR.Admin.WebApi/Controllers/UploadController.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Infrastructure; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -using System; -using System.IO; -using ZR.Admin.WebApi.Filters; -using ZR.Common; - -namespace ZR.Admin.WebApi.Controllers -{ - [Route("[controller]/[action]")] - public class UploadController : BaseController - { - private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - private OptionsSetting OptionsSetting; - private IWebHostEnvironment WebHostEnvironment; - public UploadController(IOptions optionsSetting, IWebHostEnvironment webHostEnvironment) - { - OptionsSetting = optionsSetting.Value; - WebHostEnvironment = webHostEnvironment; - } - /// - /// 存储文件 - /// - /// - /// - [HttpPost] - [Verify] - [ActionPermissionFilter(Permission = "system")] - public IActionResult SaveFile([FromForm(Name = "file")] IFormFile formFile) - { - if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传图片不能为空"); - string fileExt = Path.GetExtension(formFile.FileName); - string fileName = FileUtil.HashFileName(Guid.NewGuid().ToString()).ToLower() + fileExt; - string finalFilePath = Path.Combine(WebHostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads"), fileName); - finalFilePath = finalFilePath.Replace("\\", "/").Replace("//", "/"); - - if (!Directory.Exists(Path.GetDirectoryName(finalFilePath))) - { - Directory.CreateDirectory(Path.GetDirectoryName(finalFilePath)); - } - - using (var stream = new FileStream(finalFilePath, FileMode.Create)) - { - formFile.CopyToAsync(stream); - } - - string accessPath = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads").Replace("\\", " /")}{fileName}"; - return ToResponse(ResultCode.SUCCESS, new { accessPath, fullPath = finalFilePath }); - } - } -} diff --git a/ZR.Admin.WebApi/Controllers/business/GendemoController.cs b/ZR.Admin.WebApi/Controllers/business/GendemoController.cs deleted file mode 100644 index 0fdfee2..0000000 --- a/ZR.Admin.WebApi/Controllers/business/GendemoController.cs +++ /dev/null @@ -1,154 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using SqlSugar; -using Infrastructure; -using Infrastructure.Attribute; -using Infrastructure.Enums; -using Infrastructure.Model; -using Mapster; -using ZR.Model.Dto; -using ZR.Model.Models; -using ZR.Service.Business; -using ZR.Admin.WebApi.Extensions; -using ZR.Admin.WebApi.Filters; -using ZR.Common; -using Infrastructure.Extensions; - -namespace ZR.Admin.WebApi.Controllers -{ - /// - /// 代码生成演示Controller - /// - /// @author zr - /// @date 2021-11-24 - /// - [Verify] - [Route("business/Gendemo")] - public class GendemoController : BaseController - { - /// - /// 代码生成演示接口 - /// - private readonly IGendemoService _GendemoService; - - public GendemoController(IGendemoService GendemoService) - { - _GendemoService = GendemoService; - } - - /// - /// 查询代码生成演示列表 - /// - /// - [HttpGet("list")] - [ActionPermissionFilter(Permission = "business:gendemo:list")] - public IActionResult QueryGendemo([FromQuery] GendemoQueryDto parm) - { - //开始拼装查询条件 - var predicate = Expressionable.Create(); - - //TODO 自己实现搜索条件查询语法参考Sqlsugar,默认查询所有 - //predicate = predicate.And(m => m.Name.Contains(parm.Name)); - - var response = _GendemoService.GetPages(predicate.ToExpression(), parm); - - return SUCCESS(response); - } - - /// - /// 查询代码生成演示详情 - /// - /// - /// - [HttpGet("{Id}")] - [ActionPermissionFilter(Permission = "business:gendemo:query")] - public IActionResult GetGendemo(int Id) - { - var response = _GendemoService.GetId(Id); - - return SUCCESS(response); - } - - /// - /// 添加代码生成演示 - /// - /// - [HttpPost] - [ActionPermissionFilter(Permission = "business:gendemo:add")] - [Log(Title = "代码生成演示", BusinessType = BusinessType.INSERT)] - public IActionResult AddGendemo([FromBody] GendemoDto parm) - { - if (parm == null) - { - throw new CustomException("请求参数错误"); - } - //从 Dto 映射到 实体 - var model = parm.Adapt().ToCreate(HttpContext); - - return SUCCESS(_GendemoService.Add(model, it => new - { - it.Name, - it.Icon, - it.ShowStatus, - it.AddTime, - it.Sex, - it.Sort, - it.BeginTime, - it.EndTime, - it.Remark, - })); - } - - /// - /// 更新代码生成演示 - /// - /// - [HttpPut] - [ActionPermissionFilter(Permission = "business:gendemo:update")] - [Log(Title = "代码生成演示", BusinessType = BusinessType.UPDATE)] - public IActionResult UpdateGendemo([FromBody] GendemoDto parm) - { - if (parm == null) - { - throw new CustomException("请求实体不能为空"); - } - //从 Dto 映射到 实体 - var model = parm.Adapt().ToUpdate(HttpContext); - - var response = _GendemoService.Update(w => w.Id == model.Id, it => new Gendemo() - { - //Update 字段映射 - Name = model.Name, - Icon = model.Icon, - ShowStatus = model.ShowStatus, - AddTime = model.AddTime, - Sex = model.Sex, - Sort = model.Sort, - BeginTime = model.BeginTime, - EndTime = model.EndTime, - Remark = model.Remark, - }); - - return SUCCESS(response); - } - - /// - /// 删除代码生成演示 - /// - /// - [HttpDelete("{ids}")] - [ActionPermissionFilter(Permission = "business:gendemo:delete")] - [Log(Title = "代码生成演示", BusinessType = BusinessType.DELETE)] - public IActionResult DeleteGendemo(string ids) - { - int[] idsArr = Tools.SpitIntArrary(ids); - if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); } - - var response = _GendemoService.Delete(idsArr); - - return SUCCESS(response); - } - } -} \ No newline at end of file diff --git a/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs b/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs index d2cb61f..8f8faca 100644 --- a/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs +++ b/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs @@ -1,6 +1,7 @@ using Infrastructure; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System; @@ -67,7 +68,7 @@ namespace ZR.Admin.WebApi.Extensions { var uid = context.User.FindFirstValue(ClaimTypes.PrimarySid); - return !string.IsNullOrEmpty(uid) ? long.Parse(uid) : 0 ; + return !string.IsNullOrEmpty(uid) ? long.Parse(uid) : 0; } public static string GetName(this HttpContext context) { @@ -75,6 +76,16 @@ namespace ZR.Admin.WebApi.Extensions return uid; } + + /// + /// ClaimsIdentity + /// + /// + /// + public static IEnumerable GetClaims(this HttpContext context) + { + return context.User?.Identities; + } //public static int GetRole(this HttpContext context) //{ // var roleid = context.User.FindFirstValue(ClaimTypes.Role) ?? "0"; @@ -84,9 +95,7 @@ namespace ZR.Admin.WebApi.Extensions public static string GetUserAgent(this HttpContext context) { - var str = context.Request.Headers["User-Agent"]; - - return str; + return context.Request.Headers["User-Agent"]; } /// @@ -96,9 +105,7 @@ namespace ZR.Admin.WebApi.Extensions /// public static string GetToken(this HttpContext context) { - var str = context.Request.Headers["Token"]; - - return str; + return context.Request.Headers["Authorization"]; } public static ClientInfo GetClientInfo(this HttpContext context) @@ -116,12 +123,12 @@ namespace ZR.Admin.WebApi.Extensions } /// - /// 登录cookie写入 + ///组装Claims /// /// /// /// - public static List WriteCookies(this HttpContext context, LoginUser user) + public static List AddClaims(this HttpContext context, LoginUser user) { //1、创建Cookie保存用户信息,使用claim var claims = new List() @@ -138,13 +145,21 @@ namespace ZR.Admin.WebApi.Extensions { claims.Add(new Claim("perm", string.Join(",", user.Permissions))); } + + //写入Cookie + //WhiteCookie(context, claims); + return claims; + } + + private static void WhiteCookie(HttpContext context, List claims) + { //2.创建声明主题 指定认证方式 这里使用cookie var claimsIdentity = new ClaimsIdentity(claims, "Login"); Task.Run(async () => { await context.SignInAsync( - CookieAuthenticationDefaults.AuthenticationScheme,//这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。 + JwtBearerDefaults.AuthenticationScheme,//这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme一定要与前面的配置一样,这样对应的登录授权才会生效。 new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties() { @@ -153,7 +168,6 @@ namespace ZR.Admin.WebApi.Extensions ExpiresUtc = DateTimeOffset.Now.AddDays(1),//有效时间 }); }).Wait(); - return claims; } } diff --git a/ZR.Admin.WebApi/Extensions/SwaggerExtension.cs b/ZR.Admin.WebApi/Extensions/SwaggerExtension.cs new file mode 100644 index 0000000..40f9d49 --- /dev/null +++ b/ZR.Admin.WebApi/Extensions/SwaggerExtension.cs @@ -0,0 +1,57 @@ +using Infrastructure; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.Filters; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace ZR.Admin.WebApi.Extensions +{ + public static class SwaggerExtension + { + public static void AddSwaggerConfig(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + IWebHostEnvironment hostEnvironment = App.GetRequiredService(); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo + { + Title = "ZrAdmin.NET Api - .NET5", + Version = "v1", + Description = "", + }); + //if (CurrentEnvironment.IsDevelopment()) + //{ + //添加文档注释 + c.IncludeXmlComments(Path.Combine(hostEnvironment.ContentRootPath, "ZRAdmin.xml"), true); + //} + //参考文章:http://www.zyiz.net/tech/detail-134965.html + //需要安装包Swashbuckle.AspNetCore.Filters + // 开启权限小锁 需要在对应的Action上添加[Authorize]才能看到 + c.OperationFilter(); + c.OperationFilter(); + + //在header 中添加token,传递到后台 + c.OperationFilter(); + + c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, + new OpenApiSecurityScheme + { + In = ParameterLocation.Header, + Description = "请输入Login接口返回的Token,前置Bearer。示例:Bearer {Token}", + Name = "Authorization",//jwt默认的参数名称, + Type = SecuritySchemeType.ApiKey, //指定ApiKey + BearerFormat = "JWT",//标识承载令牌的格式 该信息主要是出于文档目的 + Scheme = JwtBearerDefaults.AuthenticationScheme//授权中要使用的HTTP授权方案的名称 + }); + }); + } + } +} diff --git a/ZR.Admin.WebApi/Filters/VerifyAttribute.cs b/ZR.Admin.WebApi/Filters/VerifyAttribute.cs index cbfaff1..2b4db73 100644 --- a/ZR.Admin.WebApi/Filters/VerifyAttribute.cs +++ b/ZR.Admin.WebApi/Filters/VerifyAttribute.cs @@ -10,6 +10,7 @@ using NLog; using System; using System.Linq; using ZR.Admin.WebApi.Extensions; +using ZR.Admin.WebApi.Framework; using ZR.Model.System; namespace ZR.Admin.WebApi.Filters @@ -44,12 +45,10 @@ namespace ZR.Admin.WebApi.Filters string ip = HttpContextExtension.GetClientUserIp(context.HttpContext); string url = context.HttpContext.Request.Path; var isAuthed = context.HttpContext.User.Identity.IsAuthenticated; - // 检查登陆 - 在SignIn中判断用户合法性,将登陆信息保存在Cookie中,在SignOut中移除登陆信息 var userName = context.HttpContext.User.Identity.Name; //使用jwt token校验2020-11-21 - //string token = context.HttpContext.Request.Headers["Token"]; - LoginUser info = Framework.JwtUtil.GetLoginUser(context.HttpContext); + LoginUser info = JwtUtil.GetLoginUser(context.HttpContext); if (info != null && info.UserId > 0) { @@ -58,7 +57,7 @@ namespace ZR.Admin.WebApi.Filters else { string msg = $"请求访问:{url}授权认证失败,无法访问系统资源"; - logger.Info(msg); + logger.Info($"用户{userName}{msg}"); context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg)); } diff --git a/ZR.Admin.WebApi/Framework/JwtUtil.cs b/ZR.Admin.WebApi/Framework/JwtUtil.cs index 1f7f073..75f237a 100644 --- a/ZR.Admin.WebApi/Framework/JwtUtil.cs +++ b/ZR.Admin.WebApi/Framework/JwtUtil.cs @@ -18,8 +18,6 @@ namespace ZR.Admin.WebApi.Framework /// public class JwtUtil { - public static readonly string KEY = "asdfghjklzxcvbnm"; - /// /// 获取用户身份信息 /// @@ -28,6 +26,7 @@ namespace ZR.Admin.WebApi.Framework public static LoginUser GetLoginUser(HttpContext httpContext) { string token = HttpContextExtension.GetToken(httpContext); + if (!string.IsNullOrEmpty(token)) { return ValidateJwtToken(ParseToken(token)); @@ -42,21 +41,52 @@ namespace ZR.Admin.WebApi.Framework /// public static string GenerateJwtToken(List claims) { + JwtSettings jwtSettings = new(); + ConfigUtils.Instance.Bind("JwtSettings", jwtSettings); + var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(KEY); - var expires = ConfigUtils.Instance.GetAppConfig("sysConfig:tokenExpire", 10); + var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey); + claims.Add(new Claim("Audience", jwtSettings.Audience)); + claims.Add(new Claim("Issuer", jwtSettings.Issuer)); + var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), - //Issuer = "", - //Audience = "", - Expires = DateTime.Now.AddMinutes(expires), + Issuer = jwtSettings.Issuer, + Audience = jwtSettings.Audience, + IssuedAt = DateTime.Now,//token生成时间 + Expires = DateTime.Now.AddMinutes(jwtSettings.Expire), + TokenType = "Bearer", + //对称秘钥,签名证书 SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } + /// + /// 验证Token + /// + /// + public static TokenValidationParameters ValidParameters() + { + JwtSettings jwtSettings = new(); + ConfigUtils.Instance.Bind("JwtSettings", jwtSettings); + var key = Encoding.ASCII.GetBytes(jwtSettings.SecretKey); + + var tokenDescriptor = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + ValidateIssuer = true, + ValidateAudience = true, + ValidIssuer = jwtSettings.Issuer, + ValidAudience = jwtSettings.Audience, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateLifetime = true,//是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比 + RequireExpirationTime = true,//过期时间 + }; + return tokenDescriptor; + } /// /// 从令牌中获取数据声明 /// @@ -65,21 +95,13 @@ namespace ZR.Admin.WebApi.Framework public static IEnumerable ParseToken(string token) { var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(KEY); + var validateParameter = ValidParameters(); + token = token.Replace("Bearer ", ""); try { - tokenHandler.ValidateToken(token, new TokenValidationParameters - { - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(key), - ValidateIssuer = false, - ValidateAudience = false, - // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later) - ClockSkew = TimeSpan.Zero - }, out SecurityToken validatedToken); + tokenHandler.ValidateToken(token, validateParameter, out SecurityToken validatedToken); - //{{"alg":"HS256","typ":"JWT"}.{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid":"2","unique_name":"ry","nameid":"2","given_name":"若依","nbf":1606654010,"exp":1606740410,"iat":1606654010}} - var jwtToken = (JwtSecurityToken)validatedToken; + var jwtToken = tokenHandler.ReadJwtToken(token); return jwtToken.Claims; } catch (Exception ex) diff --git a/ZR.Admin.WebApi/Properties/launchSettings.json b/ZR.Admin.WebApi/Properties/launchSettings.json index d3473a5..8fd0a5e 100644 --- a/ZR.Admin.WebApi/Properties/launchSettings.json +++ b/ZR.Admin.WebApi/Properties/launchSettings.json @@ -2,11 +2,11 @@ "profiles": { "ZRAdmin": { "commandName": "Project", - "launchBrowser": true, + "launchBrowser": false, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "" + "ASPNETCORE_ENVIRONMENT": "Production" }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" + "applicationUrl": "http://localhost:8888" } } } \ No newline at end of file diff --git a/ZR.Admin.WebApi/Startup.cs b/ZR.Admin.WebApi/Startup.cs index aa0e1ce..7e334ba 100644 --- a/ZR.Admin.WebApi/Startup.cs +++ b/ZR.Admin.WebApi/Startup.cs @@ -2,6 +2,7 @@ using Hei.Captcha; using Infrastructure; using Infrastructure.Extensions; using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; @@ -12,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; using SqlSugar.IOC; +using Swashbuckle.AspNetCore.Filters; using System; using System.Collections.Generic; using System.IO; @@ -42,7 +44,7 @@ namespace ZR.Admin.WebApi { c.AddPolicy("Policy", policy => { - policy.WithOrigins(corsUrls.Split(',', System.StringSplitOptions.RemoveEmptyEntries)) + policy.WithOrigins(corsUrls.Split(',', StringSplitOptions.RemoveEmptyEntries)) .AllowAnyHeader()//ͷ .AllowCredentials()//cookie .AllowAnyMethod();//ⷽ @@ -55,35 +57,37 @@ namespace ZR.Admin.WebApi services.AddSession(); services.AddHttpContextAccessor(); - //Cookie ֤ - services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); //Model services.Configure(Configuration); + services.Configure(Configuration); + var jwtSettings = new JwtSettings(); + Configuration.Bind("JwtSettings", jwtSettings); - InjectRepositories(services); + //Cookie ֤ + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }).AddCookie() + .AddJwtBearer(o => + { + o.TokenValidationParameters = JwtUtil.ValidParameters(); + }); + + InjectServices(services); services.AddMvc(options => { options.Filters.Add(typeof(GlobalActionMonitor));//ȫע쳣 }) - .AddMvcLocalization() - .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeConverter()); options.JsonSerializerOptions.Converters.Add(new JsonConverterUtil.DateTimeNullConverter()); }); - services.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", new OpenApiInfo { Title = "ZrAdmin", Version = "v1" }); - if (CurrentEnvironment.IsDevelopment()) - { - //ĵע - c.IncludeXmlComments("ZRAdmin.xml", true); - } - }); + services.AddSwaggerConfig(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -111,7 +115,9 @@ namespace ZR.Admin.WebApi //app.UseAuthenticationAuthenticationммݵǰHttpеCookieϢHttpContext.Userԣõ //ֻapp.UseAuthentication֮עмܹHttpContext.Userжȡֵ //ҲΪʲôǿapp.UseAuthenticationһҪapp.UseMvcǰ棬ΪֻASP.NET CoreMVCмвܶȡHttpContext.Userֵ + //1.ȿ֤ app.UseAuthentication(); + //2.ٿȨ app.UseAuthorization(); app.UseSession(); app.UseResponseCaching(); @@ -133,7 +139,7 @@ namespace ZR.Admin.WebApi /// עServices /// /// - private void InjectRepositories(IServiceCollection services) + private void InjectServices(IServiceCollection services) { services.AddAppService(); @@ -148,12 +154,12 @@ namespace ZR.Admin.WebApi SugarIocServices.AddSqlSugar(new List() { new IocConfig() { - ConfigId = "0", //ݿ + ConfigId = "0", ConnectionString = connStr, DbType = (IocDbType)dbType, IsAutoCloseConnection = true//Զͷ }, new IocConfig() { - ConfigId = "1", // ⻧õ + ConfigId = "1", ConnectionString = connStrBus, DbType = (IocDbType)dbType_bus, IsAutoCloseConnection = true//Զͷ @@ -161,14 +167,13 @@ namespace ZR.Admin.WebApi }); //ʽ ӡSQL - DbScoped.SugarScope.GetConnection(0).Aop.OnLogExecuting = (sql, pars) => + DbScoped.SugarScope.GetConnection("0").Aop.OnLogExecuting = (sql, pars) => { - Console.BackgroundColor = ConsoleColor.Yellow; Console.WriteLine("SQL䡿" + sql.ToLower() + "\r\n" + DbScoped.SugarScope.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); }; //ӡ־ - DbScoped.SugarScope.GetConnection(0).Aop.OnError = (e) => + DbScoped.SugarScope.GetConnection("0").Aop.OnError = (e) => { Console.WriteLine($"[ִSql]{e.Message}SQL={e.Sql}"); Console.WriteLine(); @@ -177,7 +182,6 @@ namespace ZR.Admin.WebApi //ʽ ӡSQL DbScoped.SugarScope.GetConnection(1).Aop.OnLogExecuting = (sql, pars) => { - Console.BackgroundColor = ConsoleColor.Yellow; Console.WriteLine("SQLBus" + sql.ToLower() + "\r\n" + DbScoped.SugarScope.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); }; diff --git a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj index a5b7c72..07c5a31 100644 --- a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj +++ b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj @@ -15,27 +15,27 @@ - - + - - - - - - - - - - + + + + + + + + + + + @@ -60,49 +60,14 @@ Always - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - + - - - - - - Always - - - Always - + diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json index 8b29429..b8dcce0 100644 --- a/ZR.Admin.WebApi/appsettings.json +++ b/ZR.Admin.WebApi/appsettings.json @@ -15,26 +15,34 @@ "urls": "http://localhost:8888", //Ŀurl "sysConfig": { "DBCommandTimeout": 10, - "tokenExpire": 1440, //Jwt tokenʱʱ䣨֣ "cors": "http://localhost:8887" //ַ"," }, + "JwtSettings": { + "Issuer": "https://localhost:8888", + "Audience": "https://localhost:8888", + "SecretKey": "Hello-key-ZRADMIN.NET-20210101", + "Expire": 5 + }, "DemoMode": false, //Ƿʾģʽ "DbKey": "", //ݿkey "Upload": { "UploadDirectory": "/", "UploadUrl": "http://localhost:8888" }, - "QIQIU_OSS": { + //ƴ洢 + "ALIYUN_OSS": { "REGIONID": "cn-hangzhou", "KEY": "XX", - "SECRET": "XX" + "SECRET": "XX", + "bucketName": "bucketName", + "domainUrl": "http://xxx.xxx.com" //Դ }, "gen": { - "conn": "server=LAPTOP-STKF2M8H\\SQLEXPRESS;user=zr;pwd=abc;database={database};Trusted_Connection=SSPI", + "conn": "server=LAPTOP-STKF2M8H\\SQLEXPRESS;user=zr;pwd=abc;database=ZrAdmin;Trusted_Connection=SSPI", "dbType": 1, //MySql = 0, SqlServer = 1 "autoPre": true, //Զȥǰ׺ "author": "zr", - "tablePrefix": "live_,sys_" //"ǰ׺ǰ׺öŷָ", + "tablePrefix": "sys_" //"ǰ׺ǰ׺öŷָ", }, //Ϣ "MailOptions": { diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ControllersTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ControllersTemplate.txt deleted file mode 100644 index 27824d5..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ControllersTemplate.txt +++ /dev/null @@ -1,138 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using SqlSugar; -using Infrastructure; -using Infrastructure.Attribute; -using Infrastructure.Enums; -using Infrastructure.Model; -using Mapster; -using {ModelsNamespace}.Dto; -using {ModelsNamespace}.Models; -using {ServicesNamespace}.Business; -using {ApiControllerNamespace}.Extensions; -using {ApiControllerNamespace}.Filters; -using ZR.Common; -using Infrastructure.Extensions; - -namespace {ApiControllerNamespace}.Controllers -{ - /// - /// {FunctionName}Controller - /// - /// @author {Author} - /// @date {DateTime} - /// - [Verify] - [Route("{ModuleName}/{ModelName}")] - public class {ModelName}Controller: BaseController - { - /// - /// {FunctionName}接口 - /// - private readonly I{ModelName}Service _{ModelName}Service; - - public {ModelName}Controller(I{ModelName}Service {ModelName}Service) - { - _{ModelName}Service = {ModelName}Service; - } - - /// - /// 查询{FunctionName}列表 - /// - /// - [HttpGet("list")] - [ActionPermissionFilter(Permission = "{Permission}:list")] - public IActionResult Query{ModelName}([FromQuery] {ModelName}QueryDto parm) - { - //开始拼装查询条件 - var predicate = Expressionable.Create<{ModelName}>(); - - //TODO 自己实现搜索条件查询语法参考Sqlsugar,默认查询所有 - //predicate = predicate.And(m => m.Name.Contains(parm.Name)); - - var response = _{ModelName}Service.GetPages(predicate.ToExpression(), parm); - - return SUCCESS(response); - } - - /// - /// 查询{FunctionName}详情 - /// - /// - /// - [HttpGet("{{PrimaryKey}}")] - [ActionPermissionFilter(Permission = "{Permission}:query")] - public IActionResult Get{ModelName}({PKCsharpType} {PrimaryKey}) - { - var response = _{ModelName}Service.GetId({PrimaryKey}); - - return SUCCESS(response); - } - - /// - /// 添加{FunctionName} - /// - /// - [HttpPost] - [ActionPermissionFilter(Permission = "{Permission}:add")] - [Log(Title = "{FunctionName}", BusinessType = BusinessType.INSERT)] - public IActionResult Add{ModelName}([FromBody] {ModelName}Dto parm) - { - if (parm == null) - { - throw new CustomException("请求参数错误"); - } - //从 Dto 映射到 实体 - var model = parm.Adapt<{ModelName}>().ToCreate(HttpContext); - - return SUCCESS(_{ModelName}Service.Add(model, it => new - { -{InsertColumn} - })); - } - - /// - /// 更新{FunctionName} - /// - /// - [HttpPut] - [ActionPermissionFilter(Permission = "{Permission}:update")] - [Log(Title = "{FunctionName}", BusinessType = BusinessType.UPDATE)] - public IActionResult Update{ModelName}([FromBody] {ModelName}Dto parm) - { - if (parm == null) - { - throw new CustomException("请求实体不能为空"); - } - //从 Dto 映射到 实体 - var model = parm.Adapt<{ModelName}>().ToUpdate(HttpContext); - - var response = _{ModelName}Service.Update(w => w.{PrimaryKey} == model.{PrimaryKey}, it => new {ModelName}() - { - //Update 字段映射 -{UpdateColumn} - }); - - return SUCCESS(response); - } - - /// - /// 删除{FunctionName} - /// - /// - [HttpDelete("{ids}")] - [ActionPermissionFilter(Permission = "{Permission}:delete")] - [Log(Title = "{FunctionName}", BusinessType = BusinessType.DELETE)] - public IActionResult Delete{ModelName}(string ids) - { - int[] idsArr = Tools.SpitIntArrary(ids); - if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); } - - var response = _{ModelName}Service.Delete(idsArr); - - return SUCCESS(response); - } - } -} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/IServiceTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/IServiceTemplate.txt deleted file mode 100644 index b64fd98..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/IServiceTemplate.txt +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using {ModelsNamespace}.Models; - -namespace {IServicsNamespace}.Business -{ - /// - /// {FunctionName}service接口 - /// - /// @author {Author} - /// @date {DateTime} - /// - public interface I{ModelTypeName}Service: IBaseService<{ModelTypeName}> - { - } -} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/InputDtoTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/InputDtoTemplate.txt deleted file mode 100644 index ded802d..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/InputDtoTemplate.txt +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using {ModelsNamespace}.Dto; -using {ModelsNamespace}.Models; - -namespace {DtosNamespace}.Dto -{ - /// - /// {FunctionName}输入对象模型 - /// - public class {ModelTypeName}Dto - { -{PropertyName} - } - - /// - /// {FunctionName}查询对象模型 - /// - public class {ModelTypeName}QueryDto: PagerInfo - { -{QueryProperty} - public DateTime? BeginTime { get; set; } - public DateTime? EndTime { get; set; } - } -} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ModelTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ModelTemplate.txt deleted file mode 100644 index 66bbcce..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ModelTemplate.txt +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace {ModelsNamespace}.Models -{ - /// - /// {FunctionName},数据实体对象 - /// - /// @author {Author} - /// @date {DateTime} - /// - [SqlSugar.SugarTable("{TableName}")] - public class {ModelTypeName} - { -{PropertyName} - } -} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/MySqlTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/MySqlTemplate.txt index aeb9db2..dd44cd0 100644 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/MySqlTemplate.txt +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/MySqlTemplate.txt @@ -1,23 +1,25 @@ -- 菜单 -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time, remark) -VALUES ('{FunctionName}', 0, 1, '{ModuleName}/{ModelTypeName}', '{ModuleName}/{ViewsFileName}/index', 0, 0, 'C', '0', '0', '{Permission}:list', 'icon1', sysdate(), '{FunctionName}菜单'); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, remark) +VALUES ('${genTable.functionName}', ${parentId}, 1, '${genTable.ModuleName}/${replaceDto.ModelTypeName}', '${genTable.ModuleName}/${genTable.BusinessName}/index', 0, 0, 'C', '0', '0', '${replaceDto.PermissionPrefix}:list', 'icon1', '', sysdate(), '${genTable.functionName}菜单'); -- 按钮父菜单id SELECT @menuId := LAST_INSERT_ID(); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}查询', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:query', '', '', sysdate(), '', NULL, ''); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time) +VALUES ('查询', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:query', '', sysdate()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}新增', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:add', '', '', sysdate(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time) +VALUES ('新增', @menuId, 2, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:add', '', sysdate()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}删除', @menuId, 2, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:delete', '', '', sysdate(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time) +VALUES ('删除', @menuId, 3, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:delete', '', sysdate()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}修改', @menuId, 3, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:update', '', '', sysdate(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time) +VALUES ('修改', @menuId, 4, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:update', '', sysdate()); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time) +VALUES ('导出', @menuId, 5, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:export', '', sysdate()); SELECT * FROM sys_menu WHERE parentId = @menuId; SELECT * FROM sys_menu WHERE menuId = @menuId; \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/RepositoryTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/RepositoryTemplate.txt deleted file mode 100644 index a073a0c..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/RepositoryTemplate.txt +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using Infrastructure.Attribute; -using {RepositoriesNamespace}.System; -using {ModelsNamespace}.Models; - -namespace {RepositoriesNamespace} -{ - /// - /// {FunctionName}仓储接口的实现 - /// - /// @author {Author} - /// @date {DateTime} - /// - [AppService(ServiceLifetime = LifeTime.Transient)] - public class {ModelTypeName}Repository : BaseRepository<{ModelTypeName}> - { - #region 业务逻辑代码 - #endregion - } -} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ServiceTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ServiceTemplate.txt deleted file mode 100644 index fe7121a..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/ServiceTemplate.txt +++ /dev/null @@ -1,27 +0,0 @@ -using Infrastructure; -using Infrastructure.Attribute; -using {ModelsNamespace}.Models; -using {IRepositoriesNamespace}; - -namespace {ServicesNamespace}.Business -{ - /// - /// {FunctionName}Service业务层处理 - /// - /// @author {Author} - /// @date {DateTime} - /// - [AppService(ServiceType = typeof(I{ModelTypeName}Service), ServiceLifetime = LifeTime.Transient)] - public class {ModelTypeName}Service: BaseService<{ModelTypeName}>, I{ModelTypeName}Service - { - private readonly {ModelTypeName}Repository _{ModelTypeName}repository; - public {ModelTypeName}Service({ModelTypeName}Repository repository) - { - _{ModelTypeName}repository = repository; - } - - #region 业务逻辑代码 - - #endregion - } -} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/SqlTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/SqlTemplate.txt index 6f5e049..df62b1c 100644 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/SqlTemplate.txt +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/SqlTemplate.txt @@ -1,22 +1,25 @@ --- {FunctionName}菜单 +-- ${genTable.functionName}菜单 INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_time, remark) -VALUES ('{FunctionName}', {ParentId}, 1, '{ModuleName}/{ModelTypeName}', '{ModuleName}/{ViewsFileName}/index', 0, 0, 'C', '0', '0', '{Permission}:list', 'icon1', GETDATE(), '{FunctionName}'); +VALUES ('${genTable.functionName}', ${parentId}, 1, '${genTable.ModuleName}/${genTable.BusinessName}', '${genTable.ModuleName}/${genTable.BusinessName}', 0, 0, 'C', '0', '0', '${replaceDto.PermissionPrefix}:list', 'icon1', GETDATE(), '${genTable.functionName}'); -- 按钮父菜单id declare @menuId int = @@identity -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}查询', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:query', '', '', GETDATE(), '', NULL, ''); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time) +VALUES ('查询', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:query', '', '', GETDATE()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}新增', @menuId, 1, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:add', '', '', GETDATE(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time) +VALUES ('新增', @menuId, 2, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:add', '', '', GETDATE()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}删除', @menuId, 2, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:delete', '', '', GETDATE(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time) +VALUES ('删除', @menuId, 3, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:delete', '', '', GETDATE()); -INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time, update_by, update_time, remark) -VALUES ('{FunctionName}修改', @menuId, 3, '#', NULL, 0, 0, 'F', '0', '0', '{Permission}:update', '', '', GETDATE(), '', NULL, NULL); +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time) +VALUES ('修改', @menuId, 4, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:update', '', '', GETDATE()); -SELECT * FROM sys_menu WHERE parentId = {ParentId}; +INSERT INTO sys_menu(menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by,create_time) +VALUES ('导出', @menuId, 5, '#', NULL, 0, 0, 'F', '0', '0', '${replaceDto.PermissionPrefix}:export', '', '', GETDATE()); + +SELECT * FROM sys_menu WHERE parentId = @menuId; SELECT * FROM sys_menu WHERE menuId = @menuId; \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplControllers.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplControllers.txt new file mode 100644 index 0000000..8d53e48 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplControllers.txt @@ -0,0 +1,184 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using SqlSugar; +using Infrastructure; +using Infrastructure.Attribute; +using Infrastructure.Enums; +using Infrastructure.Model; +using Mapster; +using ${options.ModelsNamespace}.Dto; +using ${options.ModelsNamespace}.Models; +using ${options.ServicesNamespace}.Business; +using ${options.ApiControllerNamespace}.Extensions; +using ${options.ApiControllerNamespace}.Filters; +using ZR.Common; +using Infrastructure.Extensions; +using System.Linq; + +namespace ${options.ApiControllerNamespace}.Controllers +{ + /// + /// ${genTable.functionName}Controller + /// + /// @author ${replaceDto.Author} + /// @date ${replaceDto.AddTime} + /// + [Verify] + [Route("${genTable.ModuleName}/${replaceDto.ModelTypeName}")] + public class ${replaceDto.ModelTypeName}Controller : BaseController + { + /// + /// ${genTable.FunctionName}接口 + /// + private readonly I${replaceDto.ModelTypeName}Service _${replaceDto.ModelTypeName}Service; + + public ${replaceDto.ModelTypeName}Controller(I${replaceDto.ModelTypeName}Service ${replaceDto.ModelTypeName}Service) + { + _${replaceDto.ModelTypeName}Service = ${replaceDto.ModelTypeName}Service; + } + + /// + /// 查询${genTable.FunctionName}列表 + /// + /// + [HttpGet("list")] + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:list")] + public IActionResult Query${replaceDto.ModelTypeName}([FromQuery] ${replaceDto.ModelTypeName}QueryDto parm) + { + //开始拼装查询条件 + var predicate = Expressionable.Create<${replaceDto.ModelTypeName}>(); + + //搜索条件查询语法参考Sqlsugar +${QueryCondition} +$if(genTable.SortField != "") + var response = _${replaceDto.ModelTypeName}Service.GetPages(predicate.ToExpression(), parm, x => x.${genTable.SortField}, "${genTable.SortType}"); +$else + var response = _${replaceDto.ModelTypeName}Service.GetPages(predicate.ToExpression(), parm); +$end + return SUCCESS(response); + } + + /// + /// 查询${genTable.FunctionName}详情 + /// + /// + /// + [HttpGet("{${replaceDto.PKName}}")] + [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}); + + return SUCCESS(response); + } + + /// + /// 添加${genTable.FunctionName} + /// + /// + [HttpPost] + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:add")] + [Log(Title = "${genTable.FunctionName}", BusinessType = BusinessType.INSERT)] + public IActionResult Add${replaceDto.ModelTypeName}([FromBody] ${replaceDto.ModelTypeName}Dto parm) + { + if (parm == null) + { + throw new CustomException("请求参数错误"); + } + //从 Dto 映射到 实体 + var model = parm.Adapt<${replaceDto.ModelTypeName}>().ToCreate(HttpContext); + + return SUCCESS(_${replaceDto.ModelTypeName}Service.Insert(model, it => new + { +$foreach(item in genTable.Columns) +$if((item.IsInsert)) + it.$item.CsharpField, +$end +${end} + })); + } + + /// + /// 更新${genTable.FunctionName} + /// + /// + [HttpPut] + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:update")] + [Log(Title = "${genTable.FunctionName}", BusinessType = BusinessType.UPDATE)] + public IActionResult Update${replaceDto.ModelTypeName}([FromBody] ${replaceDto.ModelTypeName}Dto parm) + { + if (parm == null) + { + throw new CustomException("请求实体不能为空"); + } + //从 Dto 映射到 实体 + var model = parm.Adapt<${replaceDto.ModelTypeName}>().ToUpdate(HttpContext); + + var response = _${replaceDto.ModelTypeName}Service.Update(w => w.${replaceDto.PKName} == model.${replaceDto.PKName}, it => new ${replaceDto.ModelTypeName}() + { + //Update 字段映射 +$foreach(item in genTable.Columns) +$if((item.IsEdit)) + $item.CsharpField = model.$item.CsharpField, +$end +${end} + }); + + return SUCCESS(response); + } + + /// + /// 删除${genTable.FunctionName} + /// + /// + [HttpDelete("{ids}")] + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:delete")] + [Log(Title = "${genTable.FunctionName}", BusinessType = BusinessType.DELETE)] + public IActionResult Delete${replaceDto.ModelTypeName}(string ids) + { + int[] idsArr = Tools.SpitIntArrary(ids); + if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); } + + var response = _${replaceDto.ModelTypeName}Service.Delete(idsArr); + + return SUCCESS(response); + } + + /// + /// ${genTable.FunctionName}导出 + /// + /// + [Log(BusinessType = BusinessType.EXPORT, IsSaveResponseData = false, Title = "${genTable.FunctionName}")] + [HttpGet("export")] + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:export")] + public IActionResult Export() + { + var list = _${replaceDto.ModelTypeName}Service.GetAll(); + + string sFileName = ExportExcel(list, "${replaceDto.ModelTypeName}", "${genTable.FunctionName}"); + return SUCCESS(new { path = "/export/" + sFileName, fileName = sFileName }); + } + +$if(genTable.SortField != "") + /// + /// 保存排序 + /// + /// + /// + /// + [ActionPermissionFilter(Permission = "${replaceDto.PermissionPrefix}:update")] + [HttpGet("ChangeSort")] + [Log(Title = "保存排序", BusinessType = BusinessType.UPDATE)] + public IActionResult ChangeSort(int id = 0, int orderNum = 0) + { + if (id <= 0) { return ToResponse(ApiResult.Error(101, "请求参数错误")); } + + bool result = _${replaceDto.ModelTypeName}Service.Update(w => w.${replaceDto.PKName} == id, it => new ${replaceDto.ModelTypeName}() { ${genTable.SortField} = orderNum });; + + return SUCCESS(result); + } +$end + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplDto.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplDto.txt new file mode 100644 index 0000000..52b05d7 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplDto.txt @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using ${options.ModelsNamespace}.Dto; +using ${options.ModelsNamespace}.Models; + +namespace ${options.DtosNamespace}.Dto +{ + /// + /// ${genTable.FunctionName}输入对象 + /// + public class ${replaceDto.ModelTypeName}Dto + { +$foreach(item in genTable.Columns) +$if((item.IsInsert || item.IsEdit || item.IsPk || item.IsIncrement)) + public $item.CsharpType$item.RequiredStr $item.CsharpField { get; set; } +$end +${end} + } + + /// + /// ${genTable.FunctionName}查询对象 + /// + public class ${replaceDto.ModelTypeName}QueryDto : PagerInfo + { +$foreach(item in genTable.Columns) +$if(item.IsQuery) + public $item.CsharpType $item.CsharpField { get; set; } +$end +${end} + + public DateTime? BeginTime { get; set; } + public DateTime? EndTime { get; set; } + } +} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplIService.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplIService.txt new file mode 100644 index 0000000..c06303e --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplIService.txt @@ -0,0 +1,15 @@ +using System; +using ${options.ModelsNamespace}.Models; + +namespace ${options.IServicsNamespace}.Business +{ + /// + /// ${genTable.FunctionName}service接口 + /// + /// @author ${replaceDto.Author} + /// @date ${replaceDto.AddTime} + /// + public interface I${replaceDto.ModelTypeName}Service: IBaseService<${replaceDto.ModelTypeName}> + { + } +} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplModel.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplModel.txt new file mode 100644 index 0000000..a6e326d --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplModel.txt @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using SqlSugar; + +namespace ${options.ModelsNamespace}.Models +{ + /// + /// ${genTable.FunctionName},数据实体对象 + /// + /// @author ${replaceDto.Author} + /// @date ${replaceDto.AddTime} + /// + [SugarTable("${genTable.TableName}")] + public class ${replaceDto.ModelTypeName} + { +$foreach(item in genTable.Columns) + /// + /// 描述 : ${item.ColumnComment} + /// 空值 :$if(item.IsRequired == "True") false $else true $end + /// +$if(item.IsPk || item.IsIncrement) + [SqlSugar.SugarColumn(IsPrimaryKey = ${item.IsPk.ToString().ToLower()}, IsIdentity = ${item.IsIncrement.ToString().ToLower()})] +$end + public $item.CsharpType$item.RequiredStr $item.CsharpField { get; set; } +${end} + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplRepository.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplRepository.txt new file mode 100644 index 0000000..cd43d77 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplRepository.txt @@ -0,0 +1,20 @@ +using System; +using Infrastructure.Attribute; +using ${options.RepositoriesNamespace}.System; +using ${options.ModelsNamespace}.Models; + +namespace ${options.RepositoriesNamespace} +{ + /// + /// ${genTable.FunctionName}仓储 + /// + /// @author ${replaceDto.Author} + /// @date ${replaceDto.AddTime} + /// + [AppService(ServiceLifetime = LifeTime.Transient)] + public class ${replaceDto.ModelTypeName}Repository : BaseRepository<${replaceDto.ModelTypeName}> + { + #region 业务逻辑代码 + #endregion + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplService.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplService.txt new file mode 100644 index 0000000..0b32e69 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplService.txt @@ -0,0 +1,27 @@ +using Infrastructure; +using Infrastructure.Attribute; +using ${options.ModelsNamespace}.Models; +using ${options.IRepositoriesNamespace}; + +namespace ${options.ServicesNamespace}.Business +{ + /// + /// ${genTable.FunctionName}Service业务层处理 + /// + /// @author ${replaceDto.Author} + /// @date ${replaceDto.AddTime} + /// + [AppService(ServiceType = typeof(I${replaceDto.ModelTypeName}Service), ServiceLifetime = LifeTime.Transient)] + public class ${replaceDto.ModelTypeName}Service : BaseService<${replaceDto.ModelTypeName}>, I${replaceDto.ModelTypeName}Service + { + private readonly ${replaceDto.ModelTypeName}Repository _${replaceDto.ModelTypeName}repository; + public ${replaceDto.ModelTypeName}Service(${replaceDto.ModelTypeName}Repository repository) : base(repository) + { + _${replaceDto.ModelTypeName}repository = repository; + } + + #region 业务逻辑代码 + + #endregion + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVue.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVue.txt new file mode 100644 index 0000000..32197e9 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVue.txt @@ -0,0 +1,276 @@ + + + diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVueApi.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVueApi.txt new file mode 100644 index 0000000..c70b678 --- /dev/null +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/TplVueApi.txt @@ -0,0 +1,79 @@ +import request from '@/utils/request' + +/** +* ${genTable.functionName}分页查询 +* @param {查询条件} data +*/ +export function list${genTable.BusinessName}(query) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}/list', + method: 'get', + params: query, + }) +} + +/** +* 新增${genTable.functionName} +* @param data +*/ +export function add${genTable.BusinessName}(data) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}', + method: 'post', + data: data, + }) +} + +/** +* 修改${genTable.functionName} +* @param data +*/ +export function update${genTable.BusinessName}(data) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}', + method: 'PUT', + data: data, + }) +} + +/** +* 获取${genTable.functionName}详情 +* @param {Id} +*/ +export function get${genTable.BusinessName}(id) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}/' + id, + method: 'get' + }) +} + +/** +* 删除${genTable.functionName} +* @param {主键} pid +*/ +export function del${genTable.BusinessName}(pid) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}/' + pid, + method: 'delete' + }) +} +// 导出${genTable.functionName} +export function export${replaceDto.ModelTypeName}(query) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}/export', + method: 'get', + params: query + }) +} + +$if(genTable.SortField != "") +//排序 +export function changeSort(data) { + return request({ + url: '${genTable.ModuleName}/${replaceDto.ModelTypeName}/ChangeSort', + method: 'get', + params: data + }) +} + +$end \ No newline at end of file diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueJsTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueJsTemplate.txt deleted file mode 100644 index 29b3edd..0000000 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueJsTemplate.txt +++ /dev/null @@ -1,59 +0,0 @@ -import request from '@/utils/request' - -/** - * {FunctionName}分页查询 - * @param {查询条件} data - */ -export function list{ModelTypeName}(query) { - return request({ - url: '{ModuleName}/{ModelTypeName}/list', - method: 'get', - params: query, - }) -} - -/** - * 新增{FunctionName} - * @param data - */ -export function add{ModelTypeName}(data) { - return request({ - url: '{ModuleName}/{ModelTypeName}', - method: 'post', - data: data, - }) -} - -/** - * 修改{FunctionName} - * @param data - */ -export function update{ModelTypeName}(data) { - return request({ - url: '{ModuleName}/{ModelTypeName}', - method: 'PUT', - data: data, - }) -} - -/** - * 获取{FunctionName}详情 - * @param {Id} {FunctionName}Id - */ -export function get{ModelTypeName}(id) { - return request({ - url: '{ModuleName}/{ModelTypeName}/' + id, - method: 'get' - }) -} - -/** - * 删除 - * @param {主键} pid - */ -export function del{ModelTypeName}(pid) { - return request({ - url: '{ModuleName}/{ModelTypeName}/' + pid, - method: 'delete' - }) -} diff --git a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueTemplate.txt b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueTemplate.txt index defbedf..1c604e5 100644 --- a/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueTemplate.txt +++ b/ZR.Admin.WebApi/wwwroot/CodeGenTemplate/VueTemplate.txt @@ -41,7 +41,9 @@ + {VueViewFormContent} + [AppService(ServiceType = typeof(ISysMenuService), ServiceLifetime = LifeTime.Transient)] - public class SysMenuService: ISysMenuService + public class SysMenuService : BaseService, ISysMenuService { public SysMenuRepository MenuRepository; public ISysRoleService SysRoleService; public SysMenuService( - SysMenuRepository menuRepository, - ISysRoleService sysRoleService) + SysMenuRepository menuRepository, + ISysRoleService sysRoleService) : base(menuRepository) { MenuRepository = menuRepository; SysRoleService = sysRoleService; diff --git a/ZR.Service/System/SysOperLogService.cs b/ZR.Service/System/SysOperLogService.cs index 043ba8c..7af4626 100644 --- a/ZR.Service/System/SysOperLogService.cs +++ b/ZR.Service/System/SysOperLogService.cs @@ -6,6 +6,7 @@ using ZR.Model.System; using ZR.Repository.System; using ZR.Service.System.IService; using Infrastructure; +using Infrastructure.Model; namespace ZR.Service.System { @@ -13,11 +14,11 @@ namespace ZR.Service.System /// 操作日志 /// [AppService(ServiceType = typeof(ISysOperLogService), ServiceLifetime = LifeTime.Transient)] - public class SysOperLogService : ISysOperLogService + public class SysOperLogService : BaseService, ISysOperLogService { public SysOperLogRepository sysOperLogRepository; - public SysOperLogService(SysOperLogRepository sysOperLog) + public SysOperLogService(SysOperLogRepository sysOperLog) : base(sysOperLog) { sysOperLogRepository = sysOperLog; } @@ -37,7 +38,7 @@ namespace ZR.Service.System /// 操作日志对象 /// /// 操作日志集合 - public List SelectOperLogList(SysOperLogDto operLog, PagerInfo pager) + public PagedInfo SelectOperLogList(SysOperLogDto operLog, PagerInfo pager) { operLog.BeginTime = DateTimeHelper.GetBeginTime(operLog.BeginTime, -1); operLog.EndTime = DateTimeHelper.GetBeginTime(operLog.EndTime, 1); diff --git a/ZR.Service/System/SysPermissionService.cs b/ZR.Service/System/SysPermissionService.cs index 607d3f9..7ebf695 100644 --- a/ZR.Service/System/SysPermissionService.cs +++ b/ZR.Service/System/SysPermissionService.cs @@ -8,6 +8,9 @@ using ZR.Service.System.IService; namespace ZR.Service.System { + /// + /// 角色权限 + /// [AppService(ServiceType = typeof(ISysPermissionService), ServiceLifetime = LifeTime.Transient)] public class SysPermissionService : ISysPermissionService { diff --git a/ZR.Service/System/SysPostService.cs b/ZR.Service/System/SysPostService.cs index 5a5e977..0767784 100644 --- a/ZR.Service/System/SysPostService.cs +++ b/ZR.Service/System/SysPostService.cs @@ -16,7 +16,7 @@ namespace ZR.Service.System public class SysPostService : BaseService, ISysPostService { public SysPostRepository PostRepository; - public SysPostService(SysPostRepository postRepository) + public SysPostService(SysPostRepository postRepository): base(postRepository) { PostRepository = postRepository; } diff --git a/ZR.Service/System/SysTasksLogService.cs b/ZR.Service/System/SysTasksLogService.cs index 7b7ae0d..f2a2ace 100644 --- a/ZR.Service/System/SysTasksLogService.cs +++ b/ZR.Service/System/SysTasksLogService.cs @@ -1,11 +1,16 @@ using Infrastructure.Attribute; using System; +using System.Linq.Expressions; +using ZR.Model; using ZR.Model.System; using ZR.Repository; using ZR.Service.System.IService; namespace ZR.Service.System { + /// + /// 任务日志 + /// [AppService(ServiceLifetime = LifeTime.Transient, ServiceType = typeof(ISysTasksLogService))] public class SysTasksLogService : BaseRepository, ISysTasksLogService { @@ -31,5 +36,10 @@ namespace ZR.Service.System Add(logModel); return logModel; } + + public PagedInfo GetPages(Expression> where, PagerInfo parm, Expression> order, string orderType) + { + throw new NotImplementedException(); + } } } diff --git a/ZR.Service/System/SysTasksQzService.cs b/ZR.Service/System/SysTasksQzService.cs index 1569287..17e6e85 100644 --- a/ZR.Service/System/SysTasksQzService.cs +++ b/ZR.Service/System/SysTasksQzService.cs @@ -1,12 +1,18 @@ using Infrastructure.Attribute; using ZR.Model.System; +using ZR.Repository.System; using ZR.Service.System.IService; namespace ZR.Service.System { + /// + /// 定时任务 + /// [AppService(ServiceType = typeof(ISysTasksQzService), ServiceLifetime = LifeTime.Transient)] public class SysTasksQzService : BaseService, ISysTasksQzService { - + public SysTasksQzService(SysTasksQzRepository repository) : base(repository) + { + } } } diff --git a/ZR.Service/System/SysUserRoleService.cs b/ZR.Service/System/SysUserRoleService.cs index 94bdfc1..183b10f 100644 --- a/ZR.Service/System/SysUserRoleService.cs +++ b/ZR.Service/System/SysUserRoleService.cs @@ -9,6 +9,9 @@ using ZR.Service.System.IService; namespace ZR.Service.System { + /// + /// 用户角色 + /// [AppService(ServiceType = typeof(ISysUserRoleService),ServiceLifetime = LifeTime.Transient)] public class SysUserRoleService: ISysUserRoleService { diff --git a/ZR.Service/System/SysUserService.cs b/ZR.Service/System/SysUserService.cs index 2fe57d4..92e08a6 100644 --- a/ZR.Service/System/SysUserService.cs +++ b/ZR.Service/System/SysUserService.cs @@ -10,6 +10,9 @@ using ZR.Service.System.IService; namespace ZR.Service { + /// + /// 系统用户 + /// [AppService(ServiceType = typeof(ISysUserService), ServiceLifetime = LifeTime.Transient)] public class SysUserService : BaseService, ISysUserService { @@ -22,7 +25,7 @@ namespace ZR.Service SysUserRepository userRepository, ISysRoleService sysRoleService, ISysUserRoleService userRoleService, - ISysUserPostService userPostService) + ISysUserPostService userPostService) : base(userRepository) { UserRepository = userRepository; RoleService = sysRoleService; diff --git a/ZR.Vue/.jsbeautifyrc b/ZR.Vue/.jsbeautifyrc new file mode 100644 index 0000000..d79fae6 --- /dev/null +++ b/ZR.Vue/.jsbeautifyrc @@ -0,0 +1,12 @@ +{ + "brace_style": "none,preserve-inline", + "indent_size": 2, + "indent_char": " ", + "jslint_happy": true, + "unformatted": [ + "" + ], + "css": { + "indent_size": 2 + } +} \ No newline at end of file diff --git a/ZR.Vue/package.json b/ZR.Vue/package.json index 873c7e6..05b455e 100644 --- a/ZR.Vue/package.json +++ b/ZR.Vue/package.json @@ -1,7 +1,6 @@ { - "name": "zr", - "version": "1.0.0", - "description": "管理系统", + "name": "zradmin", + "description": "ZrAdmnin.NET管理系统", "author": "ZR", "scripts": { "dev": "vue-cli-service serve", diff --git a/ZR.Vue/src/api/common.js b/ZR.Vue/src/api/common.js index b106f3b..a13d608 100644 --- a/ZR.Vue/src/api/common.js +++ b/ZR.Vue/src/api/common.js @@ -16,7 +16,7 @@ export function upload(data) { */ export function sendEmail(data) { return request({ - url: '/home/SendEmail', + url: '/common/SendEmail', method: 'POST', data: data, }) diff --git a/ZR.Vue/src/api/gendemo.js b/ZR.Vue/src/api/gendemo.js deleted file mode 100644 index 394e903..0000000 --- a/ZR.Vue/src/api/gendemo.js +++ /dev/null @@ -1,59 +0,0 @@ -import request from '@/utils/request' - -/** - * 代码生成演示分页查询 - * @param {查询条件} data - */ -export function listGendemo(query) { - return request({ - url: 'business/Gendemo/list', - method: 'get', - params: query, - }) -} - -/** - * 新增代码生成演示 - * @param data - */ -export function addGendemo(data) { - return request({ - url: 'business/Gendemo', - method: 'post', - data: data, - }) -} - -/** - * 修改代码生成演示 - * @param data - */ -export function updateGendemo(data) { - return request({ - url: 'business/Gendemo', - method: 'PUT', - data: data, - }) -} - -/** - * 获取代码生成演示详情 - * @param {Id} 代码生成演示Id - */ -export function getGendemo(id) { - return request({ - url: 'business/Gendemo/' + id, - method: 'get' - }) -} - -/** - * 删除 - * @param {主键} pid - */ -export function delGendemo(pid) { - return request({ - url: 'business/Gendemo/' + pid, - method: 'delete' - }) -} diff --git a/ZR.Vue/src/api/system/login.js b/ZR.Vue/src/api/system/login.js index 593f801..9adfb26 100644 --- a/ZR.Vue/src/api/system/login.js +++ b/ZR.Vue/src/api/system/login.js @@ -24,7 +24,7 @@ export function getInfo() { } // 退出方法 -export function logOut() { +export function logout() { return request({ url: '/LogOut', method: 'POST' diff --git a/ZR.Vue/src/components/TopNav/index.vue b/ZR.Vue/src/components/TopNav/index.vue index b34175e..e92d381 100644 --- a/ZR.Vue/src/components/TopNav/index.vue +++ b/ZR.Vue/src/components/TopNav/index.vue @@ -137,7 +137,7 @@ export default { window.open(key, "_blank"); } else if (key.indexOf("/redirect") !== -1) { // /redirect 路径内部打开 - this.$router.push({ path: key.replace("/redirect", "") }); + this.$router.push({ path: key.replace("/redirect", "") }).catch(err => {}); } else { // 显示左侧联动菜单 this.activeRoutes(key); diff --git a/ZR.Vue/src/components/UploadImage/index.vue b/ZR.Vue/src/components/UploadImage/index.vue index 87b3ee9..9b41c19 100644 --- a/ZR.Vue/src/components/UploadImage/index.vue +++ b/ZR.Vue/src/components/UploadImage/index.vue @@ -1,18 +1,9 @@ @@ -21,27 +12,78 @@ import { getToken } from "@/utils/auth"; export default { - components: {}, + name: "UploadImage", data() { return { - uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 + uploadImgUrl: process.env.VUE_APP_BASE_API + this.uploadUrl, // 上传的图片服务器地址 headers: { Authorization: "Bearer " + getToken(), }, + imageUrl: "", }; }, props: { - value: { + icon: { type: String, - default: "", }, + // 当前form 列名 + column: { type: String }, + // 上传地址 + uploadUrl: { + type: String, + default: "Common/UploadFile", + }, + // 文件类型, 例如['png', 'jpg', 'jpeg'] + fileType: { + type: Array, + default: () => ["png", "jpg", "jpeg"], + }, + // 大小限制(MB) + fileSize: { + type: Number, + default: 5, + }, + }, + mounted() { + this.imageUrl = this.icon; }, methods: { handleUploadSuccess(res) { - this.$emit("input", res.url); + this.$emit(`handleUploadSuccess`, res, this.column); + this.imageUrl = res.data; this.loading.close(); }, - handleBeforeUpload() { + // 上传前loading加载 + handleBeforeUpload(file) { + console.log(file) + let isImg = false; + if (this.fileType.length) { + let fileExtension = ""; + if (file.name.lastIndexOf(".") > -1) { + fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); + } + isImg = this.fileType.some((type) => { + if (file.type.indexOf(type) > -1) return true; + if (fileExtension && fileExtension.indexOf(type) > -1) return true; + return false; + }); + } else { + isImg = file.type.indexOf("image") > -1; + } + + if (!isImg) { + this.msgError( + `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!` + ); + return false; + } + if (this.fileSize) { + const isLt = file.size / 1024 / 1024 < this.fileSize; + if (!isLt) { + this.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`); + return false; + } + } this.loading = this.$loading({ lock: true, text: "上传中", diff --git a/ZR.Vue/src/main.js b/ZR.Vue/src/main.js index 408b53d..c16beb0 100644 --- a/ZR.Vue/src/main.js +++ b/ZR.Vue/src/main.js @@ -21,10 +21,14 @@ import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, import Pagination from "@/components/Pagination"; //自定义表格工具扩展 import RightToolbar from "@/components/RightToolbar" +// 富文本组件 +import Editor from "@/components/Editor"; // 字典标签组件 import DictTag from '@/components/DictTag' // 字典数据组件 // import DictData from '@/components/DictData' +// 上传图片 +import UploadImage from '@/components/UploadImage/index'; // 全局方法挂载 Vue.prototype.getDicts = getDicts @@ -53,18 +57,10 @@ Vue.prototype.msgInfo = function(msg) { Vue.component('Pagination', Pagination) Vue.component('RightToolbar', RightToolbar) Vue.component('DictTag', DictTag) - +Vue.component('Editor', Editor) +Vue.component('UploadImage', UploadImage) Vue.use(permission) -/** - * If you don't want to use mock-server - * you want to use MockJs for mock api - * you can execute: mockXHR() - * - * Currently MockJs will be used in the production environment, - * please remove it before going online! ! ! - */ - Vue.use(Element, { size: Cookies.get('size') || 'medium' // set element-ui default size }) @@ -76,4 +72,5 @@ new Vue({ router, store, render: h => h(App) -}) \ No newline at end of file +}) +console.log('后端地址:' + process.env.VUE_APP_BASE_API) \ No newline at end of file diff --git a/ZR.Vue/src/permission.js b/ZR.Vue/src/permission.js index 2b3b080..924803a 100644 --- a/ZR.Vue/src/permission.js +++ b/ZR.Vue/src/permission.js @@ -5,55 +5,41 @@ import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' -NProgress.configure({ showSpinner: false }) +NProgress.configure({ + showSpinner: false +}) const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/demo'] router.beforeEach((to, from, next) => { NProgress.start() - console.log(to.path); - const hasToken = getToken() + console.log('router to ' + to.path); - if (hasToken) { + if (getToken()) { /* has token*/ if (to.path === '/login') { next({ path: '/' }) NProgress.done() } else { if (store.getters.roles.length === 0) { - // 判断当前用户是否已拉取完user_info信息 - store.dispatch('GetInfo').then(res => { - //console.log('拉取userInfo', JSON.stringify(res)) - // 拉取user_info - const roles = res.data.roles - store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => { - - // 测试 默认静态页面 - // store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => { - // 根据roles权限生成可访问的路由表 + store.dispatch('GetInfo').then(() => { + store.dispatch('GenerateRoutes').then(accessRoutes => { router.addRoutes(accessRoutes) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 }) - next() + //next() }).catch(err => { console.error(err) - //这部不能少,否则会出现死循环 - store.dispatch('FedLogOut').then(() => { - Message.error(err) + store.dispatch('LogOut').then(() => { + console.log('弹框登录失败') + Message.error(err != undefined ? err : '登录失败') next({ path: '/' }) }) - next(`/login?redirect=${to.path}`) + //next(`/login`) }) } else { next() - // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ - // if (hasPermission(store.getters.roles, to.meta.roles)) { - // next() - // } else { - // next({ path: '/401', replace: true, query: { noGoBack: true }}) - // } - // 可删 ↑ } } } else { @@ -70,4 +56,4 @@ router.beforeEach((to, from, next) => { router.afterEach(() => { NProgress.done() -}) +}) \ No newline at end of file diff --git a/ZR.Vue/src/settings.js b/ZR.Vue/src/settings.js index 803cbc5..2b3221c 100644 --- a/ZR.Vue/src/settings.js +++ b/ZR.Vue/src/settings.js @@ -2,7 +2,7 @@ module.exports = { /** * 框架版本号 */ - version: '3.5.0', + version: '3.7.0', title: 'ZrAdmin.NET', /** * 主题颜色 diff --git a/ZR.Vue/src/store/modules/permission.js b/ZR.Vue/src/store/modules/permission.js index 093d46d..5493903 100644 --- a/ZR.Vue/src/store/modules/permission.js +++ b/ZR.Vue/src/store/modules/permission.js @@ -21,11 +21,11 @@ const permission = { }, SET_TOPBAR_ROUTES: (state, routes) => { // 顶部导航菜单默认添加统计报表栏指向首页 - // const index = [{ - // path: 'index', - // meta: { title: '系统首页', icon: 'dashboard' } - // }] - state.topbarRouters = routes; //.concat(index); + const index = [{ + // path: 'index', + // meta: { title: '系统首页', icon: 'dashboard' } + }] + state.topbarRouters = routes;//.concat(index); }, SET_SIDEBAR_ROUTERS: (state, routes) => { state.sidebarRouters = routes diff --git a/ZR.Vue/src/store/modules/user.js b/ZR.Vue/src/store/modules/user.js index 7a95dbd..32ed9ef 100644 --- a/ZR.Vue/src/store/modules/user.js +++ b/ZR.Vue/src/store/modules/user.js @@ -1,4 +1,4 @@ -import { login, logOut, getInfo } from '@/api/system/login' +import { login, logout, getInfo } from '@/api/system/login' import { getToken, setToken, removeToken } from '@/utils/auth' const user = { @@ -42,8 +42,8 @@ const user = { return new Promise((resolve, reject) => { login(username, password, code, uuid).then(res => { if (res.code == 200) { - //提交上面的mutaions方法 setToken(res.data) + //提交上面的mutaions方法 commit('SET_TOKEN', res.data) resolve()//then处理 } else { @@ -56,11 +56,7 @@ const user = { // 获取用户信息 GetInfo({ commit, state }) { return new Promise((resolve, reject) => { - getInfo(state.token).then(res => { - if (!res || res.code != 200) { - return reject(res.msg) - } - + getInfo().then(res => { const data = res.data const avatar = data.user.avatar == "" ? require("@/assets/image/profile.jpg") : data.user.avatar; @@ -83,13 +79,14 @@ const user = { // 退出系统 LogOut({ commit, state }) { + console.log('退出登录') return new Promise((resolve, reject) => { - logOut(state.token).then(() => { + logout().then((res) => { removeToken()// 必须先移除token commit('SET_TOKEN', '') commit('SET_ROLES', []) commit('SET_PERMISSIONS', []) - resolve() + resolve(res) }).catch(error => { reject(error) }) diff --git a/ZR.Vue/src/utils/auth.js b/ZR.Vue/src/utils/auth.js index 6163854..b83cc6d 100644 --- a/ZR.Vue/src/utils/auth.js +++ b/ZR.Vue/src/utils/auth.js @@ -8,7 +8,7 @@ export function getToken() { } export function setToken(token) { - console.log('set token=' + token) + // console.log('set token=' + token) return Cookies.set(TokenKey, token) } diff --git a/ZR.Vue/src/utils/request.js b/ZR.Vue/src/utils/request.js index a58006c..9cf7d49 100644 --- a/ZR.Vue/src/utils/request.js +++ b/ZR.Vue/src/utils/request.js @@ -1,7 +1,12 @@ import axios from 'axios' -import { MessageBox, Message } from 'element-ui' +import { + MessageBox, + Message +} from 'element-ui' import store from '@/store' -import { getToken } from '@/utils/auth' +import { + getToken +} from '@/utils/auth' // import errorCode from '@/utils/errorCode' // 解决后端跨域获取不到cookie问题 @@ -18,17 +23,11 @@ const service = axios.create({ // request拦截器 service.interceptors.request.use(config => { // 是否需要设置 token - // const isToken = (config.headers || {}).isToken === false - // if (getToken() && !isToken) { - // config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 - // } - // return config - // console.log(store.getters) if (getToken()) { //将token放到请求头发送给服务器,将tokenkey放在请求头中 - config.headers.Token = getToken(); + config.headers['Authorization'] = 'Bearer ' + getToken(); } else { - console.log(config) + // console.log(config) } return config; }, error => { @@ -38,50 +37,46 @@ service.interceptors.request.use(config => { // 响应拦截器 service.interceptors.response.use(res => { - if (res.status !== 200) { - Promise.reject('network error'); - return; - } - // 未设置状态码则默认成功状态 - const code = res.data.code; - const msg = res.data.msg; - - if (code == 401) { - MessageBox.confirm('登录状态已过期,请重新登录', '系统提示', { - confirmButtonText: '重新登录', - cancelButtonText: '取消', - type: 'warning' + if (res.status !== 200) { + Promise.reject('network error'); + return; } - ).then(() => { - store.dispatch('LogOut').then(() => { - location.href = process.env.VUE_APP_ROUTER_PREFIX + '/index'; - }) - }) + // 未设置状态码则默认成功状态 + const { code , msg } = res.data; - return Promise.reject() - } - else if (code == 0 || code == 110 || code == 101 || code == 403 || code == 500) { - Message({ - message: msg, - type: 'error' - }) - return Promise.reject() - } - else { - //返回标准 code/msg/data字段 - return res.data; - } -}, + if (code == 401) { + MessageBox.confirm('登录状态已过期,请重新登录', '系统提示', { + confirmButtonText: '重新登录', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + store.dispatch('LogOut').then(() => { + location.href = process.env.VUE_APP_ROUTER_PREFIX + 'index'; + }) + }) + + return Promise.reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code == 0 || code == 110 || code == 101 || code == 403 || code == 500) { + Message({ + message: msg, + type: 'error' + }) + return Promise.reject(msg) + } else { + //返回标准 code/msg/data字段 + return res.data; + } + }, error => { console.log('err' + error) - let { message } = error; + let { + message + } = error; if (message == "Network Error") { message = "后端接口连接异常"; - } - else if (message.includes("timeout")) { + } else if (message.includes("timeout")) { message = "系统接口请求超时"; - } - else if (message.includes("Request failed with status code")) { + } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } Message({ @@ -129,10 +124,10 @@ export function post(url, params) { } /** -* 提交表单 -* @param {*} url -* @param {*} data -*/ + * 提交表单 + * @param {*} url + * @param {*} data + */ export function postForm(url, data, config) { return new Promise((resolve, reject) => { axios.post(url, data, config).then(res => { diff --git a/ZR.Vue/src/utils/zipdownload.js b/ZR.Vue/src/utils/zipdownload.js index 500d371..f8cf764 100644 --- a/ZR.Vue/src/utils/zipdownload.js +++ b/ZR.Vue/src/utils/zipdownload.js @@ -14,7 +14,7 @@ export function downLoadZip(str, filename) { method: 'get', url: str, responseType: 'blob', - headers: { 'Token': getToken() } + headers: { 'Authorization': 'Bearer ' + getToken() } }).then(res => { resolveBlob(res, mimeMap.zip) }) @@ -25,7 +25,7 @@ export function downLoadExcel(str, filename) { method: 'get', url: url, responseType: 'blob', - headers: { 'Token': getToken() } + headers: { 'Authorization': 'Bearer ' + getToken() } }).then(res => { resolveExcel(res, filename) }) diff --git a/ZR.Vue/src/views/business/gendemo/index.vue b/ZR.Vue/src/views/business/gendemo/index.vue deleted file mode 100644 index a1bf969..0000000 --- a/ZR.Vue/src/views/business/gendemo/index.vue +++ /dev/null @@ -1,294 +0,0 @@ - - - diff --git a/ZR.Vue/src/views/components/dictData.vue b/ZR.Vue/src/views/components/dictData.vue index d83a2b2..1286a23 100644 --- a/ZR.Vue/src/views/components/dictData.vue +++ b/ZR.Vue/src/views/components/dictData.vue @@ -12,7 +12,7 @@ - 搜索 + 搜索 重置 diff --git a/ZR.Vue/src/views/index.vue b/ZR.Vue/src/views/index.vue index 8085410..22eeac4 100644 --- a/ZR.Vue/src/views/index.vue +++ b/ZR.Vue/src/views/index.vue @@ -43,6 +43,8 @@ Github + 更新日志 +

如果觉得不错欢迎给个⭐Star⭐收藏一下 ,这样作者才有继续免费下去的动力,谢谢!

@@ -62,7 +64,7 @@
  • Quartz.Net
  • MySql
  • Mapster
  • -
  • Epplus
  • +
  • Epplus
  • ...
  • @@ -98,56 +100,16 @@ 捐赠支持
    - 如果觉得有用你可以请作者喝杯咖啡☕表示鼓励 donate
    - + @@ -155,7 +117,7 @@ diff --git a/ZR.Vue/vue.config.js b/ZR.Vue/vue.config.js index 4a1fb79..4b9cde4 100644 --- a/ZR.Vue/vue.config.js +++ b/ZR.Vue/vue.config.js @@ -29,8 +29,8 @@ module.exports = { productionSourceMap: false, // webpack-dev-server 相关配置 devServer: { - host: '0.0.0.0', - port: 8887,// port, + host: '0.0.0.0',//项目启动host + port: 8887,// 项目启动port, open: true, proxy: { // detail: https://cli.vuejs.org/config/#devserver-proxy diff --git a/ZRAdmin.xml b/ZRAdmin.xml deleted file mode 100644 index 270066e..0000000 --- a/ZRAdmin.xml +++ /dev/null @@ -1,1016 +0,0 @@ - - - - ZR.Admin.WebApi - - - - - json输出带时间格式的 - - - - - - - - 响应返回结果 - - 受影响行数 - - - - - 全局Code使用 - - - - - - - - 代码生成演示Controller - - @author zr - @date 2021-10-10 - - - - - 代码生成演示接口 - - - - - 查询代码生成演示列表 - - - - - - 查询代码生成演示详情 - - - - - - - 添加代码生成演示 - - - - - - 更新代码生成演示 - - - - - - 删除代码生成演示 - - - - - - 代码生成 - - - - - 获取所有数据库的信息 - - - - - - 获取所有表根据数据名 - - 数据库名 - 表名 - 分页信息 - - - - - 代码生成器 - - 数据传输对象 - - - - - 获取代码生成表列表 - - 表名 - 分页信息 - - - - - 查询表字段列表 - - genTable表id - - - - - 删除代码生成 - - - - - - - 导入表结构(保存) - - - - - - - - 修改保存代码生成业务 - - 请求参数实体 - - - - - 预览代码 - - - - - - - 心跳 - - - - - - 加密 - - - - - - - 解密 - - - - - - - 发送邮件 - - 请求参数接收实体 - - - - - T4代码自动生成 - - - - - 文章接口 - - - - - 查询文章列表 - - - - - - 获取文章目录,前端没用到 - - - - - - 获取文章目录树 - - - - - - 查询文章详情 - - - - - - - 添加文章 - - - - - - 更新文章 - - - - - - 删除文章 - - - - - - 获取缓存监控数据 - - - - - - 获取服务器信息 - - - - - - 系统访问记录 - - - - - 查询登录日志 - /monitor/logininfor/list - - - - - - - - 清空登录日志 - /monitor/logininfor/clean - - - - - - /monitor/logininfor/1 - - - - - - - 查询操作日志 - - - - - - - 删除操作日志 - - - - - - - 清空操作日志 - - - - - - 参数配置Controller - - @author zhaorui - @date 2021-09-29 - - - - - 参数配置接口 - - - - - 查询参数配置列表 - - - - - - 查询参数配置详情 - - - - - - - 根据参数键名查询参数值 - - - - - - - 添加参数配置 - - - - - - 更新参数配置 - - - - - - 删除参数配置 - - - - - - 部门 - - - - - 获取部门列表 - - - - - - 查询部门列表(排除节点) - - - - - - - 获取部门下拉树列表 - - - - - - - 根据部门编号获取详细信息 - - - - - - 新增部门 - - - - - - - 修改部门 - - - - - - - 删除部门 - - - - - - 数据字典信息 - @author zr - - - - - 搜索 - - - - - - - - 根据字典类型查询字典数据信息 - - - - - - - 查询字典数据详细 - - - - - - - 添加 - - - - - - - 修改 - - - - - - - 删除字典类型 - - - - - - - 数据字典信息 - - - - - 查询 - - - - - - - - 查询字典类型详细 - - - - - - - 添加字典类型 - - - - - - - 修改字典类型 - - - - - - - 删除字典类型 - - - - - - 登录 - - - - - 登录 - - 登录对象 - - - - - 注销 - - - - - - 获取用户信息 - - - - - - 获取路由信息 - - - - - - 生成图片验证码 - - - - - - 获取菜单列表 √ - - - - - - 根据菜单编号获取详细信息 √ - - - - - - - 获取菜单下拉树列表(分配角色所需菜单) - - - - - - 获取角色菜单信息 - 加载对应角色菜单列表树 - - - - - - - 修改菜单 √ - - - - - - - 添加菜单 √ - - - - - - - 菜单删除 √ - - - - - - - 保存排序 - - - - - - - 岗位管理 - - - - - 岗位列表查询 - - - - - - 岗位查询 - - - - - - - 岗位管理 - - - - - - - 岗位管理 - - - - - - - 岗位删除 - - - - - - - 获取岗位选择框列表 - - - - - 个人中心用户信息获取 - - - - - - 修改用户 - - - - - - 修改密码 - - - - - - 修改头像 - - - - - - 角色信息 - - - - - 获取系统角色管理 - - - - - - 根据角色编号获取详细信息 - - - - - - - 添加角色 √ - - - - - - - 修改角色 √ - - - - - - - 根据角色分配菜单 - - - - - - - 角色删除 √ - - - - - - - 修改角色状态 √ - - 角色对象 - - - - - 用户管理 -> 获取用户 - /system/user/list - - - - - - 用户管理 -> 编辑、添加用户获取用户,信息查询 - - - - - - - 添加用户 - - - - - - - 修改用户 - - - - - - - 改变用户状态 - - - - - - - 删除用户 - - - - - - - 重置密码 - - - - - - 导入 ok - - 使用IFromFile必须使用name属性否则获取不到文件 - - - - - 用户模板 ok - - - - - - 根据角色编号获取已分配的用户 - - - - - - - 添加角色用户 - - - - - - 删除角色用户 - - - - - - - 获取未分配用户角色 - - - - - - - 查询日志 - - - - - - - - 删除定时任务调用日志 - - - - - - - 清空日志 - - - - - - 计划任务 - - - - - 查询计划任务列表 - - - - - - 查询单个计划任务 - - 编码 - - - - - 添加任务 - - - - - - 更新任务 - - - - - - 删除任务 - - - - - - 启动任务 - - - - - - 停止任务 - - - - - - 定时任务立即执行一次 - - - - - - - 存储文件 - - - - - - - HttpContext扩展类 - - - - - 是否是ajax请求 - - - - - - - 获取客户端IP - - - - - - - 获取请求令牌 - - - - - - - 登录cookie写入 - - - - - - - - 定时任务扩展方法 - - - - - 程序启动后添加任务计划 - - - - - - - API授权判断 - - - - - 权限字符串,例如 system:user:view - - - - - 执行Action前校验是否有权限访问 - - - - - - - - OnActionExecuting是在Action执行之前运行的方法。 - - - - - - OnActionExecuted是在Action中的代码执行之后运行的方法。 - - - - - - 记录请求,输出日志 - - - - - OnActionExecuted是在Action中的代码执行之后运行的方法。 - - - - - - 设置请求参数 - - - - - - - 授权校验访问 - 如果跳过授权登录在Action 或controller加上 AllowAnonymousAttribute - - - - - 只判断token是否正确,不判断权限 - 如果需要判断权限的在Action上加上ApiActionPermission属性标识权限类别,ActionPermissionFilter作权限处理 - - - - - - 记录用户登陆信息 - - - - - - - - - 2020-11-20 - - - - - 获取用户身份信息 - - - - - - - 生成token - - - - - - - 从令牌中获取数据声明 - - 令牌 - - - - - jwt token校验 - - - - - - - - 注册Services服务 - - - - - diff --git a/document/admin-mysql.sql b/document/admin-mysql.sql index b57bf4d..5ca36d6 100644 --- a/document/admin-mysql.sql +++ b/document/admin-mysql.sql @@ -525,7 +525,7 @@ CREATE TABLE `sys_user` ( -- ---------------------------- INSERT INTO `sys_user` VALUES (1, 0, 'admin', '管理员', '0', '', '', '0', '', 'e10adc3949ba59abbe56e057f20f883e', '0', '0', '127.0.0.1', '2021-08-23 14:03:17', 'admin', '2020-11-26 11:52:59', 'admin', '2021-08-03 10:11:24', '管理员'); INSERT INTO `sys_user` VALUES (2, 0, 'zr', 'zr', '0', NULL, NULL, '0', '', 'e10adc3949ba59abbe56e057f20f883e', '0', '0', '', '0001-01-01 00:00:00', 'admin', '2021-07-05 17:29:13', 'admin', '2021-08-02 16:53:04', '普通用户2'); -INSERT INTO `sys_user` VALUES (3, 100, 'editor', '编辑人员', '0', NULL, NULL, '2', 'http://www.izhaorui.cn/static/pay.jpg', 'E10ADC3949BA59ABBE56E057F20F883E', '0', '0', '127.0.0.1', '2021-08-19 09:27:46', 'admin', '2021-08-18 18:24:53', '', NULL, NULL); +INSERT INTO `sys_user` VALUES (3, 100, 'editor', '编辑人员', '0', NULL, NULL, '2', '', 'E10ADC3949BA59ABBE56E057F20F883E', '0', '0', '127.0.0.1', '2021-08-19 09:27:46', 'admin', '2021-08-18 18:24:53', '', NULL, NULL); SET FOREIGN_KEY_CHECKS = 1; @@ -636,7 +636,7 @@ create table sys_config ( insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow' ); insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456' ); insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' ); --- insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaOnOff', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(true开启,false关闭)'); +insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaOnOff', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(off、关闭,1、动态验证码 2、动态gif泡泡 3、泡泡 4、静态验证码)'); -- ---------------------------- -- 18、代码生成业务表 @@ -673,7 +673,7 @@ create table gen_table ( drop table if exists gen_table_column; CREATE TABLE `gen_table_column` ( `columnId` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号', - `tableName` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表名', + `tableName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表名', `tableId` bigint(20) NULL DEFAULT NULL COMMENT '归属表编号', `columnName` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '列名称', `columnComment` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '列描述', diff --git a/document/admin-sqlserver-表字段说明导入.sql b/document/admin-sqlserver-表字段说明导入.sql new file mode 100644 index 0000000..f6784ae Binary files /dev/null and b/document/admin-sqlserver-表字段说明导入.sql differ diff --git a/document/admin-sqlserver.sql b/document/admin-sqlserver.sql index bfd3bca..5487c3c 100644 Binary files a/document/admin-sqlserver.sql and b/document/admin-sqlserver.sql differ diff --git a/document/images/11.png b/document/images/11.png index 08ea386..828771e 100644 Binary files a/document/images/11.png and b/document/images/11.png differ diff --git a/document/images/12.png b/document/images/12.png index 88a55c0..06c4c1c 100644 Binary files a/document/images/12.png and b/document/images/12.png differ diff --git a/document/images/15-1.png b/document/images/15-1.png index 76fe704..d8aa996 100644 Binary files a/document/images/15-1.png and b/document/images/15-1.png differ diff --git a/document/images/15.png b/document/images/15.png index 668cd89..123fade 100644 Binary files a/document/images/15.png and b/document/images/15.png differ diff --git a/document/images/16.png b/document/images/16.png index 15af2c5..7895d07 100644 Binary files a/document/images/16.png and b/document/images/16.png differ diff --git a/document/images/17.png b/document/images/17.png index 3d416e6..c77cf17 100644 Binary files a/document/images/17.png and b/document/images/17.png differ