From cf9d8ac6248cf3d58c3b3bb7fee7cdbc805319d9 Mon Sep 17 00:00:00 2001 From: izory <791736813@qq.com> Date: Thu, 23 Sep 2021 17:31:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3linux=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E4=B8=8B=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 +++- .../Controllers/CodeGeneratorController.cs | 11 +- ZR.Admin.WebApi/NLog.config | 4 +- ZR.CodeGenerator/CodeGeneratorTool.cs | 154 ++++++++++-------- ZR.CodeGenerator/FileHelper.cs | 9 +- 5 files changed, 125 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 61387d4..93f9a2d 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,13 @@ ## 🍟概述 * 本项目适合有一定NetCore和 vue基础的开发人员 * 基于.NET 5实现的通用权限管理平台(RBAC模式)。整合最新技术高效快速开发,前后端分离模式,开箱即用。 -* 模块化架构设计,层次清晰,业务层推荐写到单独模块,框架升级不影响业务! -* 代码量少、通俗易懂、功能强大、易扩展,轻松开发从现在开始! +* 代码量少、学习简单、通俗易懂、功能强大、易扩展、轻量级,让web开发更快速、简单高效,解决70%的重复工作,专注您的业务,轻松开发从现在开始! * 前端采用Vue2.0、Element UI。 * 后端采用Net5、Sqlsugar、MySQL。 * 权限认证使用Jwt,支持多终端认证系统。 * 支持加载动态权限菜单,多方式轻松权限控制 -* 基于若依vue分离版本(java版本)修改 -~ 如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,获取第一时间更新,谢谢!~ +~ 如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,这样作者才有继续免费下去的动力,谢谢!~ ## 🍿在线体验 体验地址:http://www.izhaorui.cn:8080/ @@ -59,7 +57,30 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e 13. [X] 在线构建器:拖动表单元素生成相应的VUE代码。 14. [X] 任务系统:基于Quartz.NET定时任务执行。 15. [X] 文章管理:可以写文章记录。 -16. [X] 代码生成:可以一键生成前后端代码。 +16. [X] 代码生成:可以一键生成前后端代码(.cs、.vue、.js),自定义配置前端展示控件、让开发更快捷高效。 + +## 项目结构 + +ZRAdmin解决方案包含: + +Infrastructure[基础类库]:包框架的核心组件,包含一系列快速开发中经常用到的Utility辅助工具功能,部分核心功能的实现; + +ZR.Service[服务层类库]:提供WebApi接口调用; + +ZR.Tasks[定时任务类库]:提供项目定时任务实现功能; + +ZR.Repository[仓库层类库]:方便提供有执行存储过程的操作; + +ZR.Model[实体层类库],提供项目中的数据库表、数据传输对象; + +ZR.CodeGenerator[代码生成功能],包含代码生成的模板、方法、代码生成的下载。 + +ZR.Admin.WebApi[webapi接口]:为Vue版或其他三方系统提供接口服务。 + +ZR.Vue[前端UI]:vue版本UI层。 + +DataBase是最新数据库备份文件,目前支持MS SQL Server和MySql。 + ## 🍎演示图 @@ -104,6 +125,7 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e 2. 后台系统无需任何二次开发,直接发布即可使用 3. 前台与后台系统分离,分别为不同的系统(域名可独立) 4. 全局异常统一处理 +5. 自定义的代码生成功能 ## 💐 特别鸣谢 - 👉Ruoyi.vue:[Ruoyi](http://www.ruoyi.vip/) diff --git a/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs b/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs index c145514..13c027d 100644 --- a/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs +++ b/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Hosting; using SqlSugar; using System; using System.Collections.Generic; +using System.IO; using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Filters; using ZR.CodeGenerator; @@ -83,9 +84,9 @@ namespace ZR.Admin.WebApi.Controllers { throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空"); } - dto.ZipPath = WebHostEnvironment.WebRootPath + "\\Generatecode\\"; - dto.GenCodePath = dto.ZipPath + DateTime.Now.ToString("yyyyMMdd") + "\\"; - + dto.ZipPath = Path.Combine(WebHostEnvironment.WebRootPath, "Generatecode"); + dto.GenCodePath = Path.Combine(dto.ZipPath, DateTime.Now.ToString("yyyyMMdd")); + var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId); var getTableColumn = GenTableColumnService.GenTableColumns(dto.TableId); genTableInfo.Columns = getTableColumn; @@ -168,8 +169,8 @@ namespace ZR.Admin.WebApi.Controllers { GenTable genTable = new() { - BaseNameSpace = "ZR.", - ModuleName = "bus", + BaseNameSpace = "ZR.",//导入默认命名空间前缀 + ModuleName = "bus",//导入默认模块名 ClassName = CodeGeneratorTool.GetClassName(tableName), BusinessName = CodeGeneratorTool.GetClassName(tableName), FunctionAuthor = ConfigUtils.Instance.GetConfig(GenConstants.Gen_author), diff --git a/ZR.Admin.WebApi/NLog.config b/ZR.Admin.WebApi/NLog.config index 9921814..a6d075c 100644 --- a/ZR.Admin.WebApi/NLog.config +++ b/ZR.Admin.WebApi/NLog.config @@ -23,8 +23,8 @@ tuple = GenerateVueViews(replaceDto, dto); + Tuple tuple_1 = GenerateVueJs(replaceDto, dto); genPathList.Add(tuple.Item1); + genPathList.Add(tuple_1.Item1); WriteAndSave(tuple.Item1, tuple.Item2); + WriteAndSave(tuple_1.Item1, tuple_1.Item2); } return genPathList; //GenerateIRepository(modelTypeName, modelTypeDesc, keyTypeName, ifExsitedCovered); @@ -167,13 +172,11 @@ namespace ZR.CodeGenerator { var parentPath = generateDto.GenCodePath; //../ZR.Model - var servicesPath = parentPath + "\\" + _option.ModelsNamespace + "\\Models\\"; - if (!Directory.Exists(servicesPath)) - { - Directory.CreateDirectory(servicesPath); - } + var servicesPath = Path.Combine(parentPath, _option.ModelsNamespace, "Models"); + Console.WriteLine("创建文件夹" + servicesPath); + CreateDirectory(servicesPath); // ../ZR.Model/Models/User.cs - var fullPath = servicesPath + replaceDto.ModelTypeName + ".cs"; + var fullPath = Path.Combine(servicesPath, replaceDto.ModelTypeName + ".cs"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); @@ -185,7 +188,7 @@ namespace ZR.CodeGenerator .Replace("{KeyTypeName}", replaceDto.PKName) .Replace("{PropertyName}", replaceDto.ModelProperty) .Replace("{TableName}", replaceDto.TableName); - WriteAndSave(fullPath, content); + return Tuple.Create(fullPath, content); } @@ -197,13 +200,10 @@ namespace ZR.CodeGenerator private static Tuple GenerateInputDto(ReplaceDto replaceDto, GenerateDto generateDto) { var parentPath = generateDto.GenCodePath; - var servicesPath = parentPath + "\\" + _option.ModelsNamespace + "\\Dto\\"; - if (!Directory.Exists(servicesPath)) - { - Directory.CreateDirectory(servicesPath); - } + var servicesPath = Path.Combine(parentPath, _option.ModelsNamespace, "Dto"); + CreateDirectory(servicesPath); // ../ZR.Model/Dto/User.cs - var fullPath = servicesPath + replaceDto.ModelTypeName + "Dto.cs"; + var fullPath = Path.Combine(servicesPath, $"{replaceDto.ModelTypeName}Dto.cs"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); ; @@ -215,7 +215,7 @@ namespace ZR.CodeGenerator .Replace("{PropertyName}", replaceDto.InputDtoProperty) .Replace("{QueryProperty}", replaceDto.QueryProperty) .Replace("{ModelTypeName}", replaceDto.ModelTypeName); - WriteAndSave(fullPath, content); + return Tuple.Create(fullPath, content); } #endregion @@ -230,24 +230,20 @@ namespace ZR.CodeGenerator private static Tuple GenerateRepository(ReplaceDto replaceDto, GenerateDto generateDto) { var parentPath = generateDto.GenCodePath; - var repositoryPath = parentPath + "\\" + _option.RepositoriesNamespace + "\\Repositories\\"; - if (!Directory.Exists(repositoryPath)) - { - Directory.CreateDirectory(repositoryPath); - } - var fullPath = repositoryPath + "\\" + replaceDto.ModelTypeName + "Repository.cs"; + var repositoryPath = Path.Combine(parentPath, _option.RepositoriesNamespace, "Repositories"); + CreateDirectory(repositoryPath); + + var fullPath = Path.Combine(repositoryPath, $"{replaceDto.ModelTypeName}Repository.cs"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); var content = ReadTemplate("RepositoryTemplate.txt"); content = content.Replace("{ModelsNamespace}", _option.ModelsNamespace) - //.Replace("{IRepositoriesNamespace}", _option.IRepositoriesNamespace) .Replace("{RepositoriesNamespace}", _option.RepositoriesNamespace) .Replace("{ModelTypeName}", replaceDto.ModelTypeName) .Replace("{TableNameDesc}", replaceDto.TableDesc) .Replace("{TableName}", replaceDto.TableName); - WriteAndSave(fullPath, content); return Tuple.Create(fullPath, content); } @@ -262,12 +258,10 @@ namespace ZR.CodeGenerator private static Tuple GenerateIService(ReplaceDto replaceDto, GenerateDto generateDto) { var parentPath = generateDto.GenCodePath; - var iServicesPath = parentPath + "\\" + _option.IServicsNamespace + "\\Business\\IBusService\\"; - if (!Directory.Exists(iServicesPath)) - { - Directory.CreateDirectory(iServicesPath); - } - var fullPath = $"{iServicesPath}\\I{replaceDto.ModelTypeName}Service.cs"; + var iServicesPath = Path.Combine(parentPath, _option.IServicsNamespace, "Business", "IBusService"); + CreateDirectory(iServicesPath); + + var fullPath = Path.Combine(iServicesPath, $"I{replaceDto.ModelTypeName}Service.cs"); Console.WriteLine(fullPath); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); @@ -279,7 +273,6 @@ namespace ZR.CodeGenerator .Replace("{RepositoriesNamespace}", _option.RepositoriesNamespace) .Replace("{ModelTypeName}", replaceDto.ModelTypeName); - WriteAndSave(fullPath, content); return Tuple.Create(fullPath, content); } @@ -289,12 +282,9 @@ namespace ZR.CodeGenerator private static Tuple GenerateService(ReplaceDto replaceDto, GenerateDto generateDto) { var parentPath = generateDto.GenCodePath; - var servicesPath = parentPath + "\\" + _option.ServicesNamespace + "\\Business\\"; - if (!Directory.Exists(servicesPath)) - { - Directory.CreateDirectory(servicesPath); - } - var fullPath = servicesPath + replaceDto.ModelTypeName + "Service.cs"; + var servicesPath = Path.Combine(parentPath, _option.ServicesNamespace, "Business"); + CreateDirectory(servicesPath); + var fullPath = Path.Combine(servicesPath, $"{replaceDto.ModelTypeName}Service.cs"); Console.WriteLine(fullPath); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); @@ -308,7 +298,6 @@ namespace ZR.CodeGenerator .Replace("{ServicesNamespace}", _option.ServicesNamespace) .Replace("{ModelTypeName}", replaceDto.ModelTypeName); - WriteAndSave(fullPath, content); return Tuple.Create(fullPath, content); } @@ -321,12 +310,10 @@ namespace ZR.CodeGenerator private static Tuple GenerateControllers(ReplaceDto replaceDto, GenerateDto generateDto) { var parentPath = generateDto.GenCodePath; - var servicesPath = parentPath + "\\" + _option.ApiControllerNamespace + "\\Controllers\\business\\"; - if (!Directory.Exists(servicesPath)) - { - Directory.CreateDirectory(servicesPath); - } - var fullPath = servicesPath + replaceDto.ModelTypeName + "Controller.cs"; + var servicesPath = Path.Combine(parentPath, _option.ApiControllerNamespace, "Controllers", "business"); + CreateDirectory(servicesPath); + + var fullPath = Path.Combine(servicesPath, $"{replaceDto.ModelTypeName}Controller.cs"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); var content = ReadTemplate("ControllersTemplate.txt"); @@ -341,7 +328,7 @@ namespace ZR.CodeGenerator .Replace("{UpdateColumn}", replaceDto.UpdateColumn) .Replace("{InsertColumn}", replaceDto.InsertColumn) .Replace("{PKCsharpType}", replaceDto.PKType); - WriteAndSave(fullPath, content); + return Tuple.Create(fullPath, content); } #endregion @@ -351,14 +338,11 @@ namespace ZR.CodeGenerator /// 生成Vue页面 private static Tuple GenerateVueViews(ReplaceDto replaceDto, GenerateDto generateDto) { - //var parentPath = "..\\CodeGenerate";//若要生成到项目中将路径改成 “..\\ZR.Vue\\src” - var parentPath = $"{generateDto.GenCodePath}\\ZR.Vue\\src"; - var servicesPath = parentPath + "\\views\\" + FirstLowerCase(replaceDto.ModelTypeName); - if (!Directory.Exists(servicesPath)) - { - Directory.CreateDirectory(servicesPath); - } - var fullPath = servicesPath + "\\" + "index.vue"; + var parentPath = Path.Combine(generateDto.GenCodePath, "ZR.Vue", "src"); + var servicesPath = Path.Combine(parentPath, "views", FirstLowerCase(replaceDto.ModelTypeName)); + CreateDirectory(servicesPath); + + var fullPath = Path.Combine(servicesPath, "index.vue"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); ; @@ -376,21 +360,25 @@ namespace ZR.CodeGenerator .Replace("{primaryKey}", FirstLowerCase(replaceDto.PKName)) .Replace("{MountedMethod}", replaceDto.MountedMethod) .Replace("{VueViewEditFormRuleContent}", replaceDto.VueViewEditFormRuleContent);//添加、修改表单验证规则 - WriteAndSave(fullPath, content); + return Tuple.Create(fullPath, content); + } + public static Tuple GenerateVueJs(ReplaceDto replaceDto, GenerateDto generateDto) + { //api js - servicesPath = parentPath + "\\api\\"; - Directory.CreateDirectory(servicesPath); - fullPath = servicesPath + "\\" + FirstLowerCase(replaceDto.ModelTypeName) + ".js"; + var parentPath = Path.Combine(generateDto.GenCodePath, "ZR.Vue", "src"); + string servicesPath = Path.Combine(parentPath, "api"); + CreateDirectory(servicesPath); + + string fullPath = Path.Combine(servicesPath, FirstLowerCase(replaceDto.ModelTypeName) + ".js"); if (File.Exists(fullPath) && !generateDto.coverd) return Tuple.Create(fullPath, ""); - content = ReadTemplate("VueJsTemplate.txt"); + var content = ReadTemplate("VueJsTemplate.txt"); content = content .Replace("{ModelTypeName}", replaceDto.ModelTypeName) .Replace("{ModelTypeDesc}", replaceDto.TableDesc); - WriteAndSave(fullPath, content); return Tuple.Create(fullPath, content); } @@ -451,8 +439,9 @@ namespace ZR.CodeGenerator private static string ReadTemplate(string templateName) { string path = Environment.CurrentDirectory; - //var path = AppDomain.CurrentDomain.BaseDirectory; - string fullName = $"{path}\\wwwroot\\CodeGenTemplate\\{templateName}"; + string fullName = $"{path}/wwwroot/CodeGenTemplate/{templateName}"; + + Console.WriteLine("开始读取模板=" + fullName); string temp = fullName; string str = ""; if (!File.Exists(temp)) @@ -465,7 +454,10 @@ namespace ZR.CodeGenerator sr = new StreamReader(temp); str = sr.ReadToEnd(); // 读取文件 } - catch { } + catch (Exception ex) + { + Console.WriteLine($"读取模板出错了{ex.Message}"); + } sr?.Close(); sr?.Dispose(); return str; @@ -478,7 +470,8 @@ namespace ZR.CodeGenerator /// private static void WriteAndSave(string fileName, string content) { - Console.WriteLine(fileName); + fileName = fileName.Replace("\\", "/").Replace("//", "/"); + Console.WriteLine("写入文件:" + fileName); try { //实例化一个文件流--->与写入文件相关联 @@ -499,8 +492,34 @@ namespace ZR.CodeGenerator } } - #endregion + /// + /// 创建文件夹 + /// + /// + /// + public static bool CreateDirectory(string path) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + path = path.Replace("\\", "/").Replace("//", "/"); + } + try + { + if (!Directory.Exists(path)) + { + DirectoryInfo info = Directory.CreateDirectory(path); + Console.WriteLine("不存在创建文件夹" + info); + } + } + catch (Exception ex) + { + Console.WriteLine($"创建文件夹出错了,{ex.Message}"); + return false; + } + return true; + } + #endregion /// /// 初始化列属性字段数据 @@ -581,24 +600,21 @@ namespace ZR.CodeGenerator //生成压缩包 string zipReturnFileName = "ZR." + DateTime.Now.ToString("yyyyMMddHHmmss") + ".zip"; - if (!Directory.Exists(dto.GenCodePath)) - { - Directory.CreateDirectory(dto.GenCodePath); - } - string zipFileName = dto.ZipPath + "\\" + zipReturnFileName; + CreateDirectory(dto.GenCodePath); + string zipFileName = Path.Combine(dto.ZipPath, zipReturnFileName); if (File.Exists(zipFileName)) { File.Delete(zipFileName); } FileHelper.ZipFileDirectory(dto.GenCodePath, zipFileName, 7, "", "", "*.*"); - //FileHelper.DeleteDirectory(dto.GenCodePath); + FileHelper.DeleteDirectory(dto.GenCodePath); dto.ZipFileName = zipReturnFileName; return zipReturnFileName; } catch (Exception ex) { - Console.WriteLine(ex.Message); + Console.WriteLine("压缩文件出错。" + ex.Message); return ""; } } diff --git a/ZR.CodeGenerator/FileHelper.cs b/ZR.CodeGenerator/FileHelper.cs index 5e55e29..66c08e7 100644 --- a/ZR.CodeGenerator/FileHelper.cs +++ b/ZR.CodeGenerator/FileHelper.cs @@ -103,7 +103,7 @@ namespace ZR.CodeGenerator { strDirectory += Path.DirectorySeparatorChar; } - + Console.WriteLine("strDirectory=" + strDirectory); Crc32 crc = new Crc32(); string[] filenames = Directory.GetFileSystemEntries(strDirectory, filetype); @@ -112,8 +112,9 @@ namespace ZR.CodeGenerator if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 { string pPath = parentPath; - pPath += file.Substring(file.LastIndexOf("\\") + 1); - pPath += "\\"; + pPath += file[(file.LastIndexOf("/") + 1)..]; + pPath += "/"; + Console.WriteLine("递归路径" + pPath); ZipSetp(file, s, pPath, filetype); } else // 否则直接压缩文件 @@ -123,7 +124,7 @@ namespace ZR.CodeGenerator { byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); - string fileName = parentPath + file[(file.LastIndexOf("\\") + 1)..]; + string fileName = parentPath + file[(file.LastIndexOf("/") + 1)..]; ZipEntry entry = new ZipEntry(fileName); entry.DateTime = DateTime.Now; entry.Size = fs.Length;