diff --git a/.gitignore b/.gitignore
index c516947..34b14f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -262,3 +262,4 @@ __pycache__/
/ZRAdmin/Properties/launchSettings.json
/ZRAdmin/Properties/PublishProfiles
/ZR.Admin.WebApi/appsettings.Stage.json
+/CodeGenerate
diff --git a/Infrastructure/OptionsSetting.cs b/Infrastructure/OptionsSetting.cs
index 4aa2b2e..fb677bb 100644
--- a/Infrastructure/OptionsSetting.cs
+++ b/Infrastructure/OptionsSetting.cs
@@ -7,7 +7,9 @@ namespace Infrastructure
public class OptionsSetting
{
public static string ConnAdmin = "Conn_admin";
+ public static string Conn = "ConnDynamic";
public static string DbType = "DbType";
+ public static string CodeGenDbType = "CodeGenDbType";
public static string DbKey = "DbKey";
public string Conn_Admin { get; set; }
diff --git a/README.md b/README.md
index b86af5e..0983811 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e
日志管理:NLog、登录日志、操作日志
-工具类:验证码、丰富公共功能
+工具类:验证码、丰富公共功能、代码生成
## 🍄快速启动
需要安装:VS2019(最新版)、npm或yarn(最新版)
@@ -59,6 +59,7 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e
13. [X] 在线构建器:拖动表单元素生成相应的VUE代码。
14. [X] 任务系统:基于Quartz.NET定时任务执行。
15. [X] 文章管理:可以写文章记录。
+16. [X] 代码生成:可以一键生成前后端代码。
## 🍎演示图
@@ -82,7 +83,15 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e
 |
 |
-
+
+
+  |
+  |
+
+
+  |
+  |
+
## 🎉优势
diff --git a/ZR.Admin.WebApi/Controllers/BaseController.cs b/ZR.Admin.WebApi/Controllers/BaseController.cs
index 49413f1..119d7c4 100644
--- a/ZR.Admin.WebApi/Controllers/BaseController.cs
+++ b/ZR.Admin.WebApi/Controllers/BaseController.cs
@@ -16,34 +16,36 @@ namespace ZR.Admin.WebApi.Controllers
public static string TIME_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
public static string TIME_FORMAT_FULL_2 = "MM-dd HH:mm:ss";
- protected IActionResult SUCCESS(object data, string timeFormatStr = "MM-dd HH:mm:ss")
+ protected IActionResult SUCCESS(object data, string timeFormatStr = "yyyy-MM-dd HH:mm:ss")
{
string jsonStr = GetJsonStr(GetApiResult(data != null ? ResultCode.SUCCESS : ResultCode.FAIL, data), timeFormatStr);
return Content(jsonStr, "application/json");
}
+ protected IActionResult ToRespose(ResultCode resultCode, object data = null)
+ {
+ string jsonStr = GetJsonStr(GetApiResult(resultCode, data), "");
+ return Content(jsonStr, "application/json");
+ }
+
///
/// json输出带时间格式的
///
///
///
///
- protected IActionResult OutputJson(ApiResult apiResult, string timeFormatStr = "MM-dd HH:mm:ss")
+ protected IActionResult OutputJson(ApiResult apiResult, string timeFormatStr = "yyyy-MM-dd HH:mm:ss")
{
string jsonStr = GetJsonStr(apiResult, timeFormatStr);
return Content(jsonStr, "application/json");
}
- protected IActionResult OutputJson(long rows, string timeFormatStr = "MM-dd HH:mm:ss")
+ protected IActionResult OutputJson(long rows, string timeFormatStr = "yyyy-MM-dd HH:mm:ss")
{
string jsonStr = GetJsonStr(ToJson(rows), timeFormatStr);
return Content(jsonStr, "application/json");
}
- protected string SerializeObject(object obj)
- {
- return JsonConvert.SerializeObject(obj);
- }
///
/// 响应返回结果
diff --git a/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs b/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs
new file mode 100644
index 0000000..7cffe87
--- /dev/null
+++ b/ZR.Admin.WebApi/Controllers/CodeGeneratorController.cs
@@ -0,0 +1,90 @@
+using Infrastructure;
+using Infrastructure.Attribute;
+using Infrastructure.Enums;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using System.Collections.Generic;
+using ZR.Admin.WebApi.Filters;
+using ZR.CodeGenerator;
+using ZR.CodeGenerator.Model;
+using ZR.CodeGenerator.Service;
+using ZR.Model;
+using ZR.Model.Vo;
+
+namespace ZR.Admin.WebApi.Controllers
+{
+ ///
+ /// 代码生成
+ ///
+ [Route("tool/gen")]
+ public class CodeGeneratorController : BaseController
+ {
+ private CodeGeneraterService _CodeGeneraterService = new CodeGeneraterService();
+
+ ///
+ /// 获取所有数据库的信息
+ ///
+ ///
+ [HttpGet("getDbList")]
+ [ActionPermissionFilter(Permission = "tool:gen:list")]
+ public IActionResult GetListDataBase()
+ {
+ var dbList = _CodeGeneraterService.GetAllDataBases();
+ var defaultDb = dbList.Count > 0 ? dbList[0] : null;
+ return SUCCESS(new { dbList, defaultDb });
+ }
+
+ ///
+ ///获取所有表根据数据名
+ ///
+ /// 数据库名
+ /// 表名
+ /// 分页信息
+ ///
+ [HttpGet("getTableList")]
+ [ActionPermissionFilter(Permission = "tool:gen:list")]
+ 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);
+ }
+
+ ///
+ /// 获取表格列
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("getColumnInfo")]
+ [ActionPermissionFilter(Permission = "tool:gen:list")]
+ public IActionResult QueryColumnInfo(string dbName, string tableName)
+ {
+ if (string.IsNullOrEmpty(dbName) || string.IsNullOrEmpty(tableName))
+ return ToRespose(ResultCode.PARAM_ERROR);
+
+ return SUCCESS(_CodeGeneraterService.GetColumnInfo(dbName, tableName));
+ }
+
+ ///
+ /// 代码生成器
+ ///
+ /// 数据传输对象
+ ///
+ [HttpPost("genCode")]
+ [Log(Title = "代码生成", BusinessType = BusinessType.GENCODE)]
+ [ActionPermissionFilter(Permission = "tool:gen:code")]
+ public IActionResult Generate([FromBody] GenerateDto dto)
+ {
+ if (string.IsNullOrEmpty(dto.tableName))
+ {
+ throw new CustomException(ResultCode.CUSTOM_ERROR, "请求参数为空");
+ }
+ DbTableInfo dbTableInfo = new() { Name = dto.tableName };
+ CodeGeneratorTool.Generate(dbTableInfo, dto);
+
+ return SUCCESS(dbTableInfo);
+ }
+ }
+}
diff --git a/ZR.Admin.WebApi/Extensions/EntityExtension.cs b/ZR.Admin.WebApi/Extensions/EntityExtension.cs
index d518656..c472ed5 100644
--- a/ZR.Admin.WebApi/Extensions/EntityExtension.cs
+++ b/ZR.Admin.WebApi/Extensions/EntityExtension.cs
@@ -10,13 +10,13 @@ namespace ZR.Admin.WebApi.Extensions
{
var types = source.GetType();
- var worker = new IdWorker(1, 1);
- if (types.GetProperty("ID") != null)
- {
- long id = worker.NextId();
+ //var worker = new IdWorker(1, 1);
+ //if (types.GetProperty("ID") != null)
+ //{
+ // long id = worker.NextId();
- types.GetProperty("ID").SetValue(source, id.ToString(), null);
- }
+ // types.GetProperty("ID").SetValue(source, id.ToString(), null);
+ //}
if (types.GetProperty("CreateTime") != null)
{
diff --git a/ZR.Admin.WebApi/Filters/ActionPermissionFilter.cs b/ZR.Admin.WebApi/Filters/ActionPermissionFilter.cs
index 88258d7..1f87286 100644
--- a/ZR.Admin.WebApi/Filters/ActionPermissionFilter.cs
+++ b/ZR.Admin.WebApi/Filters/ActionPermissionFilter.cs
@@ -54,7 +54,7 @@ namespace ZR.Admin.WebApi.Filters
bool isDemoMode = ConfigUtils.Instance.GetAppConfig("DemoMode", false);
//演示公开环境屏蔽权限
- string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear" };
+ string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "code" };
if (isDemoMode && (denyPerms.Any(f => Permission.ToLower().Contains(f.ToLower())) || Permission.Equals("system")))
{
context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "演示模式 , 不允许操作" });
diff --git a/ZR.Admin.WebApi/Template/ControllersTemplate.txt b/ZR.Admin.WebApi/Template/ControllersTemplate.txt
new file mode 100644
index 0000000..6d8d8b2
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/ControllersTemplate.txt
@@ -0,0 +1,134 @@
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using ZR.Admin.WebApi.Filters;
+using ZR.Admin.WebApi.Controllers;
+using ZR.Service.Business;
+using SqlSugar;
+using Infrastructure;
+using Infrastructure.Attribute;
+using Infrastructure.Enums;
+using Infrastructure.Model;
+using Mapster;
+using ZR.Admin.WebApi.Extensions;
+using {ModelsNamespace}.Dto;
+using {ModelsNamespace}.Models;
+
+namespace ZRAdmin.Controllers
+{
+ ///
+ /// 代码自动生成
+ ///
+
+ [Verify]
+ [Route("bus/{ModelName}")]
+ public class {ControllerName}Controller: BaseController
+ {
+ ///
+ /// {FileName}接口
+ ///
+ private readonly I{ServiceName} _{ServiceName};
+
+ public {ControllerName}Controller(I{ServiceName} {ServiceName})
+ {
+ _{ServiceName} = {ServiceName};
+ }
+
+ ///
+ /// 查询{FileName}列表
+ ///
+ ///
+ [HttpGet("list")]
+ [ActionPermissionFilter(Permission = "{Permission}:list")]
+ public IActionResult Query([FromQuery] {ModelName}QueryDto parm)
+ {
+ //开始拼装查询条件
+ var predicate = Expressionable.Create<{ModelName}>();
+
+ //TODO 搜索条件
+ //predicate = predicate.And(m => m.Name.Contains(parm.Name));
+
+ var response = _{ServiceName}.GetPages(predicate.ToExpression(), parm);
+
+ return SUCCESS(response);
+ }
+
+ ///
+ /// 查询{FileName}详情
+ ///
+ ///
+ ///
+ [HttpGet("{{primaryKey}}")]
+ [ActionPermissionFilter(Permission = "{Permission}:query")]
+ public IActionResult Get({KeyTypeName} {primaryKey})
+ {
+ var response = _{ServiceName}.GetId({primaryKey});
+
+ return SUCCESS(response);
+ }
+
+ ///
+ /// 添加{FileName}
+ ///
+ ///
+ [HttpPost]
+ [ActionPermissionFilter(Permission = "{Permission}:add")]
+ [Log(Title = "{FileName}添加", BusinessType = BusinessType.INSERT)]
+ public IActionResult Create([FromBody] {ModelName}Dto parm)
+ {
+ if (parm == null)
+ {
+ throw new CustomException("请求参数错误");
+ }
+ //从 Dto 映射到 实体
+ var addModel = parm.Adapt<{ModelName}>().ToCreate();
+ //addModel.CreateID = User.Identity.Name;
+
+ return SUCCESS(_{ServiceName}.Add(addModel));
+ }
+
+ ///
+ /// 更新{FileName}
+ ///
+ ///
+ [HttpPut]
+ [ActionPermissionFilter(Permission = "{Permission}:update")]
+ [Log(Title = "{FileName}修改", BusinessType = BusinessType.UPDATE)]
+ public IActionResult Update([FromBody] {ModelName}Dto parm)
+ {
+ if (parm == null)
+ {
+ throw new CustomException("请求实体不能为空");
+ }
+ //从 Dto 映射到 实体
+ var updateModel = parm.Adapt<{ModelName}>().ToCreate();
+ //updateModel.CreateID = User.Identity.Name;
+
+ var response = _{ServiceName}.Update(w => w.{primaryKey} == updateModel.{primaryKey}, it => new {ModelName}()
+ {
+ //TODO 字段映射
+ {updateColumn}
+ });
+
+ return SUCCESS(response);
+ }
+
+ ///
+ /// 删除{FileName}
+ ///
+ ///
+ [HttpDelete("{{primaryKey}}")]
+ [ActionPermissionFilter(Permission = "{Permission}:delete")]
+ [Log(Title = "{FileName}删除", BusinessType = BusinessType.DELETE)]
+ public IActionResult Delete({KeyTypeName} {primaryKey} = 0)
+ {
+ if ({primaryKey} <= 0) { return OutputJson(ApiResult.Error($"删除失败Id 不能为空")); }
+
+ // 删除{FileName}
+ var response = _{ServiceName}.Delete({primaryKey});
+
+ return SUCCESS(response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ZR.Admin.WebApi/Template/IServiceTemplate.txt b/ZR.Admin.WebApi/Template/IServiceTemplate.txt
new file mode 100644
index 0000000..8e3692b
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/IServiceTemplate.txt
@@ -0,0 +1,12 @@
+using System;
+using {ModelsNamespace}.Models;
+
+namespace {IServicsNamespace}.Business
+{
+ ///
+ /// 定义{TableNameDesc}服务接口
+ ///
+ public interface I{ModelTypeName}Service: IBaseService<{ModelTypeName}>
+ {
+ }
+}
diff --git a/ZR.Admin.WebApi/Template/InputDtoTemplate.txt b/ZR.Admin.WebApi/Template/InputDtoTemplate.txt
new file mode 100644
index 0000000..656cdad
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/InputDtoTemplate.txt
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using {ModelsNamespace}.Dto;
+using {ModelsNamespace}.Models;
+
+namespace {DtosNamespace}.Dto
+{
+ ///
+ /// {TableNameDesc}输入对象模型
+ ///
+ public class {ModelTypeName}Dto
+ {
+{PropertyName}
+ }
+
+ public class {ModelTypeName}QueryDto: PagerInfo
+ {
+ public DateTime? BeginTime { get; set; }
+ public DateTime? EndTime { get; set; }
+ }
+}
diff --git a/ZR.Admin.WebApi/Template/ModelTemplate.txt b/ZR.Admin.WebApi/Template/ModelTemplate.txt
new file mode 100644
index 0000000..7d9a00a
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/ModelTemplate.txt
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+
+namespace {ModelsNamespace}.Models
+{
+ ///
+ /// {TableNameDesc},数据实体对象
+ ///
+ [SqlSugar.SugarTable("{TableName}")]
+ public class {ModelTypeName}
+ {
+{PropertyName}
+ }
+}
diff --git a/ZR.Admin.WebApi/Template/RepositoryTemplate.txt b/ZR.Admin.WebApi/Template/RepositoryTemplate.txt
new file mode 100644
index 0000000..e39f922
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/RepositoryTemplate.txt
@@ -0,0 +1,25 @@
+using System;
+using Infrastructure.Attribute;
+using {RepositoriesNamespace}.System;
+using {ModelsNamespace}.Models;
+
+namespace {RepositoriesNamespace}
+{
+ ///
+ /// 代码生成器生成
+ /// {TableNameDesc}仓储接口的实现
+ ///
+ [AppService(ServiceLifetime = LifeTime.Transient)]
+ public class {ModelTypeName}Repository : BaseRepository
+ {
+ public {ModelTypeName}Repository()
+ {
+ }
+
+ #region 业务逻辑代码
+
+
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/ZR.Admin.WebApi/Template/ServiceTemplate.txt b/ZR.Admin.WebApi/Template/ServiceTemplate.txt
new file mode 100644
index 0000000..1c88cf6
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/ServiceTemplate.txt
@@ -0,0 +1,32 @@
+using Infrastructure;
+using Infrastructure.Attribute;
+using Infrastructure.Extensions;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZR.Common;
+using {ModelsNamespace}.Models;
+using {IRepositoriesNamespace};
+using {ServicesNamespace}.IService;
+
+namespace {ServicesNamespace}.Business
+{
+ ///
+ /// 代码生成器生成
+ ///
+ [AppService(ServiceType = typeof(I{ModelTypeName}Service), ServiceLifetime = LifeTime.Transient)]
+ public class {ModelTypeName}Service: BaseService<{ModelTypeName}>, I{ModelTypeName}Service
+ {
+ private readonly {ModelTypeName}Repository _repository;
+ public {ModelTypeName}Service({ModelTypeName}Repository repository)
+ {
+ _repository = repository;
+ }
+
+ #region 业务逻辑代码
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/ZR.Admin.WebApi/Template/VueJsTemplate.txt b/ZR.Admin.WebApi/Template/VueJsTemplate.txt
new file mode 100644
index 0000000..719dfc7
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/VueJsTemplate.txt
@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+/**
+ * {ModelTypeDesc}分页查询
+ * @param {查询条件} data
+ */
+export function list{ModelTypeName}(data) {
+ return request({
+ url: 'bus/{ModelTypeName}/list',
+ method: 'get',
+ params: data,
+ })
+}
+
+/**
+ * 新增{ModelTypeDesc}
+ * @param data
+ */
+export function add{ModelTypeName}(data) {
+ return request({
+ url: '/bus/{ModelTypeName}',
+ method: 'post',
+ data: data,
+ })
+}
+
+/**
+ * 修改{ModelTypeDesc}
+ * @param data
+ */
+export function update{ModelTypeName}(data) {
+ return request({
+ url: '/bus/{ModelTypeName}',
+ method: 'PUT',
+ data: data,
+ })
+}
+
+/**
+ * 获取{ModelTypeDesc}详情
+ * @param {Id} {ModelTypeDesc}Id
+ */
+export function get{ModelTypeName}(id) {
+ return request({
+ url: '/bus/{ModelTypeName}/' + id,
+ method: 'get'
+ })
+}
+
+/**
+ * 删除
+ * @param {主键} pid
+ */
+export function del{ModelTypeName}(pid) {
+ return request({
+ url: '/bus/{ModelTypeName}/' + pid,
+ method: 'delete'
+ })
+}
diff --git a/ZR.Admin.WebApi/Template/VueTemplate.txt b/ZR.Admin.WebApi/Template/VueTemplate.txt
new file mode 100644
index 0000000..ac347d3
--- /dev/null
+++ b/ZR.Admin.WebApi/Template/VueTemplate.txt
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+ 新增
+
+
+ 修改
+
+
+ 删除
+
+
+
+
+
+
+
+ {VueViewListContent}
+
+
+ 编辑
+
+ 删除
+
+
+
+
+
+
+
+
+
+ {VueViewFormContent}
+
+
+
+
+
+
+
+
diff --git a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj
index 9f82d37..cbbf3ed 100644
--- a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj
+++ b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj
@@ -32,6 +32,7 @@
+
@@ -56,6 +57,30 @@
TextTemplatingFileGenerator
Controller.cs
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
@@ -63,6 +88,16 @@
+
+
+
+ Always
+
+
+ Always
+
+
+
diff --git a/ZR.Admin.WebApi/appsettings.Development.json b/ZR.Admin.WebApi/appsettings.Development.json
index 8d64c6d..61f44c9 100644
--- a/ZR.Admin.WebApi/appsettings.Development.json
+++ b/ZR.Admin.WebApi/appsettings.Development.json
@@ -6,9 +6,9 @@
"Microsoft.Hosting.Lifetime": "Information"
}
},
- "appName": "ZR Admin System",
"ConnectionStrings": {
- "Conn_Admin": "server=127.0.0.1;database=admin;user=zr;pwd=abc"
+ "Conn_Admin": "server=127.0.0.1;user=zr;pwd=abc;database=admin",
+ "ConnDynamic": "server=127.0.0.1;user=zr;pwd=abc;database={database}"//ʹ
},
"urls": "http://localhost:8888", //url
"sysConfig": {
@@ -18,6 +18,7 @@
"DemoMode": false, //Ƿʾģʽ
"DbKey": "",
"DbType": 0, //MySql = 0, SqlServer = 1, Sqlite = 2, Oracle = 3, PostgreSQL = 4,
+ "CodeGenDbType": 0,//ݿ
"Upload": {
"UploadDirectory": "/",
"UploadUrl": "http://localhost:8888"
diff --git a/ZR.Admin.WebApi/appsettings.Production.json b/ZR.Admin.WebApi/appsettings.Production.json
index 68ffe8e..8983e0f 100644
--- a/ZR.Admin.WebApi/appsettings.Production.json
+++ b/ZR.Admin.WebApi/appsettings.Production.json
@@ -5,26 +5,5 @@
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
- },
- "appName": "ZR Admin system",
- "ConnectionStrings": {
- "Conn_Admin": "server=127.0.0.1;database=admin;user=zr;pwd=abc"
- },
- "urls": "http://localhost:8888",
- "sysConfig": {
- "DBCommandTimeout": 10,
- "cors": "http://localhost:8887"
- },
- "DemoMode": false, //Ƿʾģʽ
- "DbKey": "",
- "DbType": 0, //MySql = 0, SqlServer = 1, Sqlite = 2, Oracle = 3, PostgreSQL = 4,
- "Upload": {
- "UploadDirectory": "/",
- "UploadUrl": "http://localhost:8888"
- },
- "ALYUN_OCS": {
- "REGIONID": "cn-hangzhou",
- "KEY": "XX",
- "SECRET": "XX"
}
}
diff --git a/ZR.CodeGenerator/CodeGenerateOption.cs b/ZR.CodeGenerator/CodeGenerateOption.cs
new file mode 100644
index 0000000..abb237f
--- /dev/null
+++ b/ZR.CodeGenerator/CodeGenerateOption.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ZR.CodeGenerator
+{
+ public class CodeGenerateOption
+ {
+ ///
+ /// 项目命名空间
+ ///
+ public string BaseNamespace { get; set; }
+ ///
+ /// 数据实体命名空间
+ ///
+ public string ModelsNamespace { get; set; }
+ ///
+ /// 输入输出数据实体名称空间
+ ///
+ public string DtosNamespace { get; set; }
+ ///
+ /// 仓储接口命名空间
+ ///
+ public string IRepositoriesNamespace { get; set; }
+ ///
+ /// 仓储实现名称空间
+ ///
+ public string RepositoriesNamespace { get; set; }
+ ///
+ /// 服务接口命名空间
+ ///
+ public string IServicsNamespace { get; set; }
+ ///
+ /// 服务接口实现命名空间
+ ///
+ public string ServicesNamespace { get; set; }
+
+ ///
+ /// Api控制器命名空间
+ ///
+ public string ApiControllerNamespace { get; set; }
+
+ ///
+ /// 去掉的表头字符
+ ///
+ public string ReplaceTableNameStr { get; set; }
+ ///
+ /// 要生数据的表,用“,”分割
+ ///
+ public string TableList { get; set; }
+ }
+}
diff --git a/ZR.CodeGenerator/CodeGenerateTemplate.cs b/ZR.CodeGenerator/CodeGenerateTemplate.cs
new file mode 100644
index 0000000..e8c1796
--- /dev/null
+++ b/ZR.CodeGenerator/CodeGenerateTemplate.cs
@@ -0,0 +1,152 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ZR.CodeGenerator.CodeGenerator;
+
+namespace ZR.CodeGenerator
+{
+ public class CodeGenerateTemplate
+ {
+ #region Template
+
+ public static string GetVueJsMethod(DbColumnInfo dbColumnInfo)
+ {
+ string columnName = CodeGeneratorTool.FirstLowerCase(dbColumnInfo.DbColumnName);
+ string js = "";
+ if (CodeGeneratorTool.imageFiled.Any(f => columnName.Contains(f)))
+ {
+ js += $"handleUpload{columnName}Success(res, file) {{\n";
+ js += $" this.form.{columnName} = URL.createObjectURL(file.raw);\n";
+ js += " // this.$refs.upload.clearFiles();\n";
+ js += "},\n";
+ }
+ return js;
+ }
+
+ //rules
+ public static string GetFormRules(DbColumnInfo dbFieldInfo)
+ {
+ string vueViewEditFromRuleContent = "";
+ //Rule 规则验证
+ if (!dbFieldInfo.IsNullable && !dbFieldInfo.IsIdentity)
+ {
+ vueViewEditFromRuleContent += $" {dbFieldInfo.DbColumnName}: [\n";
+ vueViewEditFromRuleContent += $" {{ required: true, message:\"请输入{dbFieldInfo.ColumnDescription}\", trigger: \"blur\"}},\n";
+ //vueViewEditFromRuleContent += " { min: 2, max: 50, message: \"长度在 2 到 50 个字符\", trigger:\"blur\" }\n";
+ vueViewEditFromRuleContent += " ],\n";
+ }
+
+ return vueViewEditFromRuleContent;
+ }
+
+ //model 属性
+ public static string GetModelTemplate(DbColumnInfo dbFieldInfo)
+ {
+ string columnName = dbFieldInfo.DbColumnName.Substring(0, 1).ToUpper() + dbFieldInfo.DbColumnName[1..];
+ var modelcontent = "";
+ modelcontent += " /// \n";
+ modelcontent += $" /// 描述 :{dbFieldInfo.ColumnDescription}\n";
+ modelcontent += $" /// 空值 :{dbFieldInfo.IsNullable}\n";
+ modelcontent += $" /// 默认 :{dbFieldInfo.DefaultValue}\n";
+ modelcontent += " /// \n";
+ if (dbFieldInfo.IsIdentity || dbFieldInfo.IsPrimarykey)
+ {
+ modelcontent += $" [SqlSugar.SugarColumn(IsPrimaryKey = {dbFieldInfo.IsPrimarykey.ToString().ToLower()}, IsIdentity = {dbFieldInfo.IsIdentity.ToString().ToLower()})]\n";
+ }
+ modelcontent += $" public {TableMappingHelper.GetPropertyDatatype(dbFieldInfo.DataType)} {columnName} {{ get; set; }}\n\r";
+ return modelcontent;
+ }
+ //DTO model
+ public static string GetDtoContent(DbColumnInfo dbFieldInfo)
+ {
+ string columnName = dbFieldInfo.DbColumnName.Substring(0, 1).ToUpper() + dbFieldInfo.DbColumnName[1..];
+ string InputDtoContent = "";
+ InputDtoContent += $" public {TableMappingHelper.GetPropertyDatatype(dbFieldInfo.DataType)} {columnName} {{ get; set; }}\n\r";
+
+ return InputDtoContent;
+ }
+
+ //form-item
+ public static string GetVueViewFormContent(DbColumnInfo dbFieldInfo)
+ {
+ string columnName = CodeGeneratorTool.FirstLowerCase(dbFieldInfo.DbColumnName);
+ string labelName = CodeGeneratorTool.GetLabelName(dbFieldInfo.ColumnDescription, columnName);
+ string vueViewFromContent = "";
+ string labelDisabled = dbFieldInfo.IsIdentity ? ":disabled=\"true\"" : "";
+ string placeHolder = dbFieldInfo.IsIdentity ? "" : $"请输入{CodeGeneratorTool.GetLabelName(dbFieldInfo.ColumnDescription, columnName)}";
+
+ if (dbFieldInfo.DataType == "datetime")
+ {
+ //时间
+ vueViewFromContent += $" \n";
+ vueViewFromContent += $" \n";
+ vueViewFromContent += " \n";
+ }
+ else if (CodeGeneratorTool.imageFiled.Any(f => columnName.Contains(f)))
+ {
+ //图片
+ vueViewFromContent += $" \n";
+ vueViewFromContent += $" \n";
+ vueViewFromContent += $"
\n";
+ vueViewFromContent += " \n";
+ vueViewFromContent += " \n";
+ vueViewFromContent += $" \n";
+ vueViewFromContent += " \n";
+ }
+ else if (CodeGeneratorTool.radioFiled.Any(f => columnName.Contains(f)) && (dbFieldInfo.DataType == "bool" || dbFieldInfo.DataType == "tinyint" || dbFieldInfo.DataType == "int"))
+ {
+ vueViewFromContent += $" ";
+ vueViewFromContent += $" \n";
+ vueViewFromContent += " {{dict.dictLabel}}\n";
+ vueViewFromContent += " \n";
+ vueViewFromContent += " \n";
+ }
+ else
+ {
+ vueViewFromContent += $" \n";
+ vueViewFromContent += $" \n";
+ vueViewFromContent += " \n";
+ }
+
+ return vueViewFromContent;
+ }
+
+ //table-column
+ public static string GetTableColumn(DbColumnInfo dbFieldInfo)
+ {
+ string columnName = CodeGeneratorTool.FirstLowerCase(dbFieldInfo.DbColumnName);
+ string label = CodeGeneratorTool.GetLabelName(dbFieldInfo.ColumnDescription, columnName);
+ string vueViewListContent = "";
+ string showToolTip = dbFieldInfo.DataType.Contains("varchar") ? ":show-overflow-tooltip=\"true\"" : "";
+
+ if (CodeGeneratorTool.imageFiled.Any(f => columnName.ToLower().Contains(f)))
+ {
+ vueViewListContent += $" \n";
+ vueViewListContent += " \n";
+ vueViewListContent += $" \n";
+ vueViewListContent += " \n";
+ vueViewListContent += " \n";
+ }
+ else if (dbFieldInfo.DataType == "bool" || dbFieldInfo.DataType == "tinyint")
+ {
+ vueViewListContent += $" \n";
+ vueViewListContent += " \n";
+ vueViewListContent += $" ";
+ vueViewListContent += $" {{scope.row.{columnName}===true?'启用':'禁用'}} \n";
+ vueViewListContent += " \n";
+ vueViewListContent += " \n";
+ }
+ else
+ {
+ //table-column
+ vueViewListContent += $" \n";
+ }
+ return vueViewListContent;
+ }
+ #endregion
+
+ }
+}
diff --git a/ZR.CodeGenerator/CodeGeneratorTool.cs b/ZR.CodeGenerator/CodeGeneratorTool.cs
new file mode 100644
index 0000000..8667eab
--- /dev/null
+++ b/ZR.CodeGenerator/CodeGeneratorTool.cs
@@ -0,0 +1,518 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ZR.CodeGenerator.Model;
+using ZR.CodeGenerator.Service;
+
+namespace ZR.CodeGenerator
+{
+ ///
+ /// 代码生成器。
+ ///
+ /// 根据指定的实体域名空间生成Repositories和Services层的基础代码文件。
+ ///
+ ///
+ public class CodeGeneratorTool
+ {
+ ///
+ /// 代码生成器配置
+ ///
+ private static CodeGenerateOption _option = new CodeGenerateOption();
+ ///
+ /// InputDto输入实体是不包含字段
+ ///
+ public static readonly string[] inputDtoNoField = new string[] { "DeleteMark", "CreateTime", "updateTime", "addtime" };
+ public static readonly string[] imageFiled = new string[] { "icon", "img", "image", "url", "pic", "photo" };
+ public static readonly string[] selectFiled = new string[] { "status", "type", "state", "sex", "gender" };
+ public static readonly string[] radioFiled = new string[] { "status", "state", "isShow", "isHidden", "ishide" };
+
+ ///
+ /// 代码生成器入口方法
+ ///
+ ///
+ ///
+ public static void Generate(DbTableInfo dbTableInfo, GenerateDto dto)
+ {
+ //_option.BaseNamespace = baseNamespace;
+ //_option.TableList = listTable;
+ _option.ReplaceTableNameStr = dto.replaceTableNameStr;
+ _option.DtosNamespace = "ZR.Model";
+ _option.ModelsNamespace = "ZR.Model";
+ _option.RepositoriesNamespace = "ZR.Repository";
+ _option.IRepositoriesNamespace = "ZR.Repository";
+ _option.IServicsNamespace = "ZR.Service";
+ _option.ServicesNamespace = "ZR.Service";
+ _option.ApiControllerNamespace = "ZR.Admin.WebApi";
+
+ CodeGeneraterService codeGeneraterService = new CodeGeneraterService();
+
+ List listField = codeGeneraterService.GetColumnInfo(dto.dbName, dbTableInfo.Name);
+ GenerateSingle(listField, dbTableInfo, dto);
+
+ //GenerateDtoProfile(_option.ModelsNamespace, profileContent, ifExsitedCovered);
+ }
+
+ ///
+ /// 单表生成代码
+ ///
+ /// 表字段集合
+ /// 表信息
+ /// 如果目标文件存在,是否覆盖。默认为false
+ public static void GenerateSingle(List listField, DbTableInfo tableInfo, GenerateDto dto)
+ {
+ bool ifExsitedCovered = dto.coverd;
+ var modelTypeName = GetModelClassName(tableInfo.Name);//表名对应C# 实体类名
+ var modelTypeDesc = tableInfo.Description;//表描述
+ var primaryKey = "id";//主键
+
+ string keyTypeName = "int";//主键数据类型
+ string modelContent = "";//数据库模型字段
+ string InputDtoContent = "";//输入模型
+ //string outputDtoContent = "";//输出模型
+ string updateColumn = "";//修改数据映射字段
+ string vueViewListContent = string.Empty;//Vue列表输出内容
+ string vueViewFormContent = string.Empty;//Vue表单输出内容
+ string vueViewEditFromContent = string.Empty;//Vue变量输出内容
+ string vueViewEditFromBindContent = string.Empty;//Vue显示初始化输出内容
+ string vueViewSaveBindContent = string.Empty;//Vue保存时输出内容
+ string vueViewEditFromRuleContent = string.Empty;//Vue数据校验
+ string vueJsMethod = string.Empty;//Vue js自定义方法
+
+ foreach (DbColumnInfo dbFieldInfo in listField)
+ {
+ string columnName = FirstLowerCase(dbFieldInfo.DbColumnName);
+
+ if (dbFieldInfo.DataType == "bool" || dbFieldInfo.DataType == "tinyint")
+ {
+ vueViewEditFromContent += $" {columnName}: 'true',\n";
+ //vueViewEditFromBindContent += $" this.form.{columnName} = res.data.{0}+''\n";
+ }
+ else
+ {
+ vueViewEditFromContent += $" {columnName}: undefined,\n";
+ //vueViewEditFromBindContent += $" {columnName}: row.{columnName},\n";
+ }
+ //vueViewSaveBindContent += string.Format(" '{0}':this.editFrom.{0},\n", columnName);
+ //主键
+ if (dbFieldInfo.IsIdentity || dbFieldInfo.IsPrimarykey)
+ {
+ primaryKey = columnName.Substring(0, 1).ToUpper() + columnName[1..];
+ keyTypeName = dbFieldInfo.DataType;
+ }
+ else
+ {
+ var tempColumnName = columnName.Substring(0, 1).ToUpper() + columnName[1..];
+ updateColumn += $" {tempColumnName} = parm.{tempColumnName},\n";
+ }
+
+ dbFieldInfo.DbColumnName = columnName;
+ modelContent += CodeGenerateTemplate.GetModelTemplate(dbFieldInfo);
+ vueViewFormContent += CodeGenerateTemplate.GetVueViewFormContent(dbFieldInfo);
+ vueJsMethod += CodeGenerateTemplate.GetVueJsMethod(dbFieldInfo);
+ vueViewListContent += CodeGenerateTemplate.GetTableColumn(dbFieldInfo);
+ vueViewEditFromRuleContent += CodeGenerateTemplate.GetFormRules(dbFieldInfo);
+ InputDtoContent += CodeGenerateTemplate.GetDtoContent(dbFieldInfo);
+ }
+ if (dto.genFiles.Contains(1))
+ {
+ GenerateModels(_option.ModelsNamespace, modelTypeName, tableInfo.Name, modelContent, modelTypeDesc, keyTypeName, ifExsitedCovered);
+ }
+ if (dto.genFiles.Contains(2))
+ {
+ GenerateInputDto(_option.ModelsNamespace, modelTypeName, modelTypeDesc, InputDtoContent, keyTypeName, ifExsitedCovered);
+ }
+ if (dto.genFiles.Contains(3))
+ {
+ GenerateRepository(modelTypeName, modelTypeDesc, tableInfo.Name, keyTypeName, ifExsitedCovered);
+ }
+ if (dto.genFiles.Contains(4))
+ {
+ GenerateIService(_option.ModelsNamespace, modelTypeName, modelTypeDesc, keyTypeName, ifExsitedCovered);
+ GenerateService(_option.ModelsNamespace, modelTypeName, modelTypeDesc, keyTypeName, ifExsitedCovered);
+ }
+ if (dto.genFiles.Contains(5))
+ {
+ GenerateControllers(modelTypeName, primaryKey, modelTypeDesc, keyTypeName, updateColumn, ifExsitedCovered);
+ }
+ if (dto.genFiles.Contains(6))
+ {
+ GenerateVueViews(modelTypeName, primaryKey, modelTypeDesc, vueViewListContent, vueViewFormContent, vueViewEditFromContent, vueViewEditFromBindContent, vueViewSaveBindContent, vueViewEditFromRuleContent, vueJsMethod, ifExsitedCovered);
+ }
+ //GenerateIRepository(modelTypeName, modelTypeDesc, keyTypeName, ifExsitedCovered);
+ //GenerateOutputDto(modelTypeName, modelTypeDesc, outputDtocontent, ifExsitedCovered);
+ }
+
+
+ #region 生成Model
+
+ ///
+ /// 生成Models文件
+ ///
+ /// 命名空间
+ /// 类名
+ /// 表名称
+ /// 表描述
+ /// 数据库表实体内容
+ /// 主键数据类型
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateModels(string modelsNamespace, string modelTypeName, string tableName, string modelContent, string modelTypeDesc, string keyTypeName, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ //../ZR.Model
+ var servicesPath = parentPath + "\\" + modelsNamespace + "\\Models\\";
+ if (!Directory.Exists(servicesPath))
+ {
+ Directory.CreateDirectory(servicesPath);
+ }
+ // ../ZR.Model/Models/User.cs
+ var fullPath = servicesPath + modelTypeName + ".cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, "");
+ var content = ReadTemplate("ModelTemplate.txt");
+ content = content
+ .Replace("{ModelsNamespace}", modelsNamespace)
+ .Replace("{ModelTypeName}", modelTypeName)
+ .Replace("{TableNameDesc}", modelTypeDesc)
+ .Replace("{KeyTypeName}", keyTypeName)
+ .Replace("{PropertyName}", modelContent)
+ .Replace("{TableName}", tableName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+
+
+ ///
+ /// 生成InputDto文件
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateInputDto(string modelsNamespace, string modelTypeName, string modelTypeDesc, string modelContent, string keyTypeName, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ var servicesPath = parentPath + "\\" + modelsNamespace + "\\Dto\\";
+ if (!Directory.Exists(servicesPath))
+ {
+ Directory.CreateDirectory(servicesPath);
+ }
+ // ../ZR.Model/Dto/User.cs
+ var fullPath = servicesPath + modelTypeName + "Dto.cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, ""); ;
+ var content = ReadTemplate("InputDtoTemplate.txt");
+ content = content
+ .Replace("{DtosNamespace}", _option.DtosNamespace)
+ .Replace("{ModelsNamespace}", modelsNamespace)
+ .Replace("{TableNameDesc}", modelTypeDesc)
+ .Replace("{KeyTypeName}", keyTypeName)
+ .Replace("{PropertyName}", modelContent)
+ .Replace("{ModelTypeName}", modelTypeName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+ #endregion
+
+ #region 生成Repository
+
+ ///
+ /// 生成Repository层代码文件
+ ///
+ ///
+ ///
+ /// 表名
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateRepository(string modelTypeName, string modelTypeDesc, string tableName, string keyTypeName, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ var repositoryPath = parentPath + "\\" + _option.RepositoriesNamespace + "\\Repositories\\";
+ if (!Directory.Exists(repositoryPath))
+ {
+ Directory.CreateDirectory(repositoryPath);
+ }
+ var fullPath = repositoryPath + "\\" + modelTypeName + "Repository.cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ 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}", modelTypeName)
+ .Replace("{TableNameDesc}", modelTypeDesc)
+ .Replace("{TableName}", tableName)
+ .Replace("{KeyTypeName}", keyTypeName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+
+ #endregion
+
+ #region 生成Service
+ ///
+ /// 生成IService文件
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateIService(string modelsNamespace, string modelTypeName, string modelTypeDesc, string keyTypeName, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ var iServicesPath = parentPath + "\\" + _option.IServicsNamespace + "\\Business\\IBusService\\";
+ if (!Directory.Exists(iServicesPath))
+ {
+ Directory.CreateDirectory(iServicesPath);
+ }
+ var fullPath = $"{iServicesPath}\\I{modelTypeName}Service.cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, "");
+ var content = ReadTemplate("IServiceTemplate.txt");
+ content = content.Replace("{ModelsNamespace}", modelsNamespace)
+ .Replace("{TableNameDesc}", modelTypeDesc)
+ .Replace("{DtosNamespace}", _option.DtosNamespace)
+ .Replace("{IServicsNamespace}", _option.IServicsNamespace)
+ .Replace("{RepositoriesNamespace}", _option.RepositoriesNamespace)
+ .Replace("{ModelTypeName}", modelTypeName)
+ .Replace("{KeyTypeName}", keyTypeName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+
+ ///
+ /// 生成Service文件
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateService(string modelsNamespace, string modelTypeName, string modelTypeDesc, string keyTypeName, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ var servicesPath = parentPath + "\\" + _option.ServicesNamespace + "\\Business\\";
+ if (!Directory.Exists(servicesPath))
+ {
+ Directory.CreateDirectory(servicesPath);
+ }
+ var fullPath = servicesPath + modelTypeName + "Service.cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, "");
+ var content = ReadTemplate("ServiceTemplate.txt");
+ content = content
+ .Replace("{IRepositoriesNamespace}", _option.IRepositoriesNamespace)
+ .Replace("{DtosNamespace}", _option.DtosNamespace)
+ .Replace("{IServicsNamespace}", _option.IServicsNamespace)
+ .Replace("{TableNameDesc}", modelTypeDesc)
+ .Replace("{ModelsNamespace}", modelsNamespace)
+ .Replace("{ServicesNamespace}", _option.ServicesNamespace)
+ .Replace("{ModelTypeName}", modelTypeName)
+ .Replace("{KeyTypeName}", keyTypeName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+
+ #endregion
+
+ #region 生成Controller
+ ///
+ /// 生成控制器ApiControllers文件
+ ///
+ /// 实体类型名称
+ /// 主键
+ /// 实体描述
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateControllers(string modelTypeName, string primaryKey, string modelTypeDesc, string keyTypeName, string updateColumn, bool ifExsitedCovered = false)
+ {
+ var parentPath = "..";
+ var servicesPath = parentPath + "\\" + _option.ApiControllerNamespace + "\\Controllers\\business\\";
+ if (!Directory.Exists(servicesPath))
+ {
+ Directory.CreateDirectory(servicesPath);
+ }
+ var fullPath = servicesPath + modelTypeName + "Controller.cs";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, "");
+ var content = ReadTemplate("ControllersTemplate.txt");
+ content = content
+ //.Replace("{DtosNamespace}", _option.DtosNamespace)
+ .Replace("{ControllerName}", modelTypeName)
+ .Replace("{ModelsNamespace}", _option.ModelsNamespace)
+ .Replace("{FileName}", modelTypeDesc)
+ .Replace("{ServiceName}", modelTypeName + "Service")
+ .Replace("{ModelName}", modelTypeName)
+ .Replace("{Permission}", modelTypeName.ToLower())
+ .Replace("{primaryKey}", primaryKey)
+ .Replace("{updateColumn}", updateColumn)
+ .Replace("{KeyTypeName}", keyTypeName);
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+ #endregion
+
+ #region 生成Vue页面
+ ///
+ /// 生成Vue页面
+ ///
+ /// 类名
+ /// 表/类描述
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 如果目标文件存在,是否覆盖。默认为false
+ private static Tuple GenerateVueViews(string modelTypeName, string primaryKey, string modelTypeDesc, string vueViewListContent, string vueViewFromContent, string vueViewEditFromContent, string vueViewEditFromBindContent, string vueViewSaveBindContent, string vueViewEditFromRuleContent, string vueJsMethod, bool ifExsitedCovered = false)
+ {
+ //var parentPath = "..\\CodeGenerate";//若要生成到项目中将路径改成 “..\\ZR.Vue\\src”
+ var parentPath = "..\\ZR.Vue\\src";
+ var servicesPath = parentPath + "\\views\\" + FirstLowerCase(modelTypeName);
+ if (!Directory.Exists(servicesPath))
+ {
+ Directory.CreateDirectory(servicesPath);
+ }
+ var fullPath = servicesPath + "\\" + "index.vue";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, ""); ;
+ var content = ReadTemplate("VueTemplate.txt");
+ content = content
+ .Replace("{fileClassName}", FirstLowerCase(modelTypeName))
+ .Replace("{VueViewListContent}", vueViewListContent)//查询 table列
+ .Replace("{VueViewFormContent}", vueViewFromContent)//添加、修改表单
+ .Replace("{ModelTypeName}", modelTypeName)
+ .Replace("{Permission}", modelTypeName.ToLower())
+ .Replace("{VueViewEditFormContent}", vueViewEditFromContent)
+ .Replace("{vueJsMethod}", vueJsMethod)
+ //.Replace("{VueViewEditFromBindContent}", vueViewEditFromBindContent)
+ //.Replace("{VueViewSaveBindContent}", vueViewSaveBindContent)
+ .Replace("{primaryKey}", FirstLowerCase(primaryKey))
+ .Replace("{VueViewEditFormRuleContent}", vueViewEditFromRuleContent);//添加、修改表单验证规则
+ WriteAndSave(fullPath, content);
+
+ //api js
+ servicesPath = parentPath + "\\api\\";
+ Directory.CreateDirectory(servicesPath);
+ fullPath = servicesPath + "\\" + FirstLowerCase(modelTypeName) + ".js";
+ Console.WriteLine(fullPath);
+ if (File.Exists(fullPath) && !ifExsitedCovered)
+ return Tuple.Create(fullPath, "");
+ content = ReadTemplate("VueJsTemplate.txt");
+ content = content
+ .Replace("{ModelTypeName}", modelTypeName)
+ .Replace("{ModelTypeDesc}", modelTypeDesc);
+ //.Replace("{fileClassName}", fileClassName)
+ WriteAndSave(fullPath, content);
+ return Tuple.Create(fullPath, content);
+ }
+
+ #endregion
+
+ #region 帮助方法
+
+ ///
+ /// 如果有前缀替换将前缀替换成空,替换下划线"_"为空再将首字母大写
+ ///
+ ///
+ ///
+ public static string GetModelClassName(string modelTypeName)
+ {
+ if (!string.IsNullOrEmpty(_option.ReplaceTableNameStr))
+ {
+ modelTypeName = modelTypeName.Replace(_option.ReplaceTableNameStr.ToString(), "");
+ }
+ modelTypeName = modelTypeName.Replace("_", "");
+ modelTypeName = modelTypeName.Substring(0, 1).ToUpper() + modelTypeName[1..];
+ return modelTypeName;
+ }
+ ///
+ /// 首字母转小写,输出前端
+ ///
+ ///
+ ///
+ public static string FirstLowerCase(string str)
+ {
+ return string.IsNullOrEmpty(str) ? str : str.Substring(0, 1).ToLower() + str[1..];
+ }
+
+ ///
+ /// 获取前端标签名
+ ///
+ ///
+ ///
+ ///
+ public static string GetLabelName(string columnDescription, string columnName)
+ {
+ return string.IsNullOrEmpty(columnDescription) ? columnName : columnDescription;
+ }
+ ///
+ /// 从代码模板中读取内容
+ ///
+ /// 模板名称,应包括文件扩展名称。比如:template.txt
+ ///
+ private static string ReadTemplate(string templateName)
+ {
+ var path = AppDomain.CurrentDomain.BaseDirectory;
+ string fullName = $"{path}\\Template\\{templateName}";
+ string temp = fullName;
+ string str = "";
+ if (!File.Exists(temp))
+ {
+ return str;
+ }
+ StreamReader sr = null;
+ try
+ {
+ sr = new StreamReader(temp);
+ str = sr.ReadToEnd(); // 读取文件
+ }
+ catch { }
+ sr?.Close();
+ sr?.Dispose();
+ return str;
+
+ }
+
+ ///
+ /// 写文件
+ ///
+ ///
+ ///
+ private static void WriteAndSave(string fileName, string content)
+ {
+ try
+ {
+ //实例化一个文件流--->与写入文件相关联
+ using var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
+ //实例化一个StreamWriter-->与fs相关联
+ using var sw = new StreamWriter(fs);
+ //开始写入
+ sw.Write(content);
+ //清空缓冲区
+ sw.Flush();
+ //关闭流
+ sw.Close();
+ fs.Close();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("写入文件出错了:" + ex.Message);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/ZR.CodeGenerator/DbProvider.cs b/ZR.CodeGenerator/DbProvider.cs
new file mode 100644
index 0000000..56525f3
--- /dev/null
+++ b/ZR.CodeGenerator/DbProvider.cs
@@ -0,0 +1,43 @@
+using Infrastructure;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ZR.CodeGenerator
+{
+ public class DbProvider
+ {
+ protected static SqlSugarScope CodeDb;
+
+ ///
+ /// 获取动态连接字符串
+ ///
+ /// 数据库名
+ ///
+ public SqlSugarScope GetSugarDbContext(string dbName = "")
+ {
+ string connStr = ConfigUtils.Instance.GetConnectionStrings(OptionsSetting.Conn).Replace("{database}", dbName);
+ int dbType = ConfigUtils.Instance.GetAppConfig(OptionsSetting.CodeGenDbType, 0);
+ if (string.IsNullOrEmpty(dbName))
+ {
+ connStr = ConfigUtils.Instance.GetConnectionStrings(OptionsSetting.ConnAdmin);
+ dbType = ConfigUtils.Instance.GetAppConfig(OptionsSetting.DbType, 0);
+ }
+ var db = new SqlSugarScope(new List()
+ {
+ new ConnectionConfig(){
+ ConnectionString = connStr,
+ DbType = (DbType)dbType,
+ IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样
+ InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
+ },
+ });
+
+ CodeDb = db;
+ return db;
+ }
+ }
+}
diff --git a/ZR.CodeGenerator/Model/GenerateDto.cs b/ZR.CodeGenerator/Model/GenerateDto.cs
new file mode 100644
index 0000000..60399fc
--- /dev/null
+++ b/ZR.CodeGenerator/Model/GenerateDto.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ZR.CodeGenerator.Model
+{
+ public class GenerateDto
+ {
+ public string[] queryColumn { get; set; }
+ ///
+ ///
+ ///
+ public string dbName { get; set; }
+ ///
+ /// 项目命名空间
+ ///
+ public string baseSpace { get; set; }
+ ///
+ /// 要生成代码的表
+ ///
+ public string tableName { get; set; }
+ ///
+ /// 要删除表名的字符串用
+ ///
+ public string replaceTableNameStr { get; set; }
+ ///
+ /// 要生成的文件
+ ///
+ public int[] genFiles { get; set; }
+ public bool coverd { get; set; } = true;
+ }
+}
diff --git a/ZR.CodeGenerator/Service/CodeGeneraterService.cs b/ZR.CodeGenerator/Service/CodeGeneraterService.cs
new file mode 100644
index 0000000..f22a3bf
--- /dev/null
+++ b/ZR.CodeGenerator/Service/CodeGeneraterService.cs
@@ -0,0 +1,52 @@
+using SqlSugar;
+using System.Collections.Generic;
+using System.Linq;
+using ZR.Model;
+
+namespace ZR.CodeGenerator.Service
+{
+ public class CodeGeneraterService : DbProvider
+ {
+ ///
+ /// 获取所有数据库名
+ ///
+ ///
+ public List GetAllDataBases()
+ {
+ var db = GetSugarDbContext();
+ var templist = db.DbMaintenance.GetDataBaseList(db.ScopedContext);
+
+ return templist;
+ }
+
+ ///
+ /// 获取所有表
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List GetAllTables(string dbName, string tableName, PagerInfo pager)
+ {
+ var tableList = GetSugarDbContext(dbName).DbMaintenance.GetTableInfoList(true);
+ if (!string.IsNullOrEmpty(tableName))
+ {
+ tableList = tableList.Where(f => f.Name.ToLower().Contains(tableName.ToLower())).ToList();
+ }
+ pager.TotalNum = tableList.Count;
+ return tableList.Skip(pager.PageSize * (pager.PageNum - 1)).Take(pager.PageSize).OrderBy(f => f.Name).ToList();
+ }
+
+ ///
+ /// 获取列信息
+ ///
+ ///
+ ///
+ ///
+ public List GetColumnInfo(string dbName, string tableName)
+ {
+ return GetSugarDbContext(dbName).DbMaintenance.GetColumnInfosByTableName(tableName, true);
+ }
+
+ }
+}
diff --git a/ZR.CodeGenerator/TableMappingHelper.cs b/ZR.CodeGenerator/TableMappingHelper.cs
index e0c9daa..44f8e38 100644
--- a/ZR.CodeGenerator/TableMappingHelper.cs
+++ b/ZR.CodeGenerator/TableMappingHelper.cs
@@ -34,6 +34,8 @@ namespace ZR.CodeGenerator.CodeGenerator
public static string GetClassNamePrefix(string tableName)
{
string[] arr = tableName.Split('_');
+ if (arr.Length <= 0) return tableName;
+
StringBuilder sb = new StringBuilder();
for (int i = 1; i < arr.Length; i++)
{
diff --git a/ZR.CodeGenerator/ZR.CodeGenerator.csproj b/ZR.CodeGenerator/ZR.CodeGenerator.csproj
index 948f805..cbcf969 100644
--- a/ZR.CodeGenerator/ZR.CodeGenerator.csproj
+++ b/ZR.CodeGenerator/ZR.CodeGenerator.csproj
@@ -11,8 +11,13 @@
-
-
+
+
+
+
+
+ PreserveNewest
+
diff --git a/ZR.Model/Models/README.txt b/ZR.Model/Models/README.txt
new file mode 100644
index 0000000..39e9872
--- /dev/null
+++ b/ZR.Model/Models/README.txt
@@ -0,0 +1 @@
+此文件夹用于存放业务代码数据库实体类
\ No newline at end of file
diff --git a/ZR.Model/System/SysMenu.cs b/ZR.Model/System/SysMenu.cs
index 1af655c..36f53f7 100644
--- a/ZR.Model/System/SysMenu.cs
+++ b/ZR.Model/System/SysMenu.cs
@@ -13,7 +13,7 @@ namespace ZR.Model.System
/// 菜单ID
///
//[Key]//非自动增长主键时使用ExplicitKey
- [SqlSugar.SugarColumn(IsPrimaryKey = true)]
+ [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public long menuId { get; set; }
///
/// 菜单名称
diff --git a/ZR.Repository/DbProvider/SugarDbContext.cs b/ZR.Repository/DbProvider/SugarDbContext.cs
index 67ec657..68f7afe 100644
--- a/ZR.Repository/DbProvider/SugarDbContext.cs
+++ b/ZR.Repository/DbProvider/SugarDbContext.cs
@@ -27,6 +27,7 @@ namespace ZR.Repository.DbProvider
{
connStr = NETCore.Encrypt.EncryptProvider.DESDecrypt(connStr, dbKey);
}
+
Db = new SqlSugarClient(new List()
{
new ConnectionConfig(){
@@ -41,6 +42,7 @@ namespace ZR.Repository.DbProvider
//调式代码 用来打印SQL
Db.Aop.OnLogExecuting = (sql, pars) =>
{
+ Console.BackgroundColor = ConsoleColor.Yellow;
Console.WriteLine("【SQL语句】" + sql.ToLower() + "\r\n" + Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
};
//出错打印日志
@@ -50,5 +52,21 @@ namespace ZR.Repository.DbProvider
Console.WriteLine();
};
}
+
+ public SqlSugarClient GetSugarDbContext(string dbName)
+ {
+ string connStr = ConfigUtils.Instance.GetConnectionStrings(OptionsSetting.Conn).Replace("{DbName}", dbName);
+ int dbType = ConfigUtils.Instance.GetAppConfig(OptionsSetting.DbType, 0);
+
+ return new SqlSugarClient(new List()
+ {
+ new ConnectionConfig(){
+ ConnectionString = connStr,
+ DbType = (DbType)dbType,
+ IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样
+ InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
+ },
+ });
+ }
}
}
diff --git a/ZR.Repository/System/SysUserRepository.cs b/ZR.Repository/System/SysUserRepository.cs
index 03ab81c..754edcd 100644
--- a/ZR.Repository/System/SysUserRepository.cs
+++ b/ZR.Repository/System/SysUserRepository.cs
@@ -29,7 +29,7 @@ namespace ZR.Repository.System
.WhereIF(!string.IsNullOrEmpty(user.UserName), it => it.UserName.Contains(user.UserName))
.WhereIF(!string.IsNullOrEmpty(user.Status), it => it.Status == user.Status)
.WhereIF(user.BeginTime != DateTime.MinValue && user.BeginTime != null, it => it.Create_time >= user.BeginTime)
- .WhereIF(user.EndTime != DateTime.MinValue && user.BeginTime != null, it => it.EndTime <= user.EndTime)
+ .WhereIF(user.EndTime != DateTime.MinValue && user.BeginTime != null, it => it.Create_time <= user.EndTime)
.WhereIF(user.DeptId != 0, it => it.DeptId == user.DeptId)
.OrderBy(it => it.UserId)
.ToPageList(pager.PageNum, pager.PageSize, ref totalCount);
diff --git a/ZR.Repository/ZR.Repository.csproj b/ZR.Repository/ZR.Repository.csproj
index c4175f5..dd8fc0f 100644
--- a/ZR.Repository/ZR.Repository.csproj
+++ b/ZR.Repository/ZR.Repository.csproj
@@ -15,4 +15,8 @@
+
+
+
+
diff --git a/ZR.Service/IBaseService.cs b/ZR.Service/IBaseService.cs
index 72959f0..e77d47b 100644
--- a/ZR.Service/IBaseService.cs
+++ b/ZR.Service/IBaseService.cs
@@ -3,8 +3,6 @@ using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
-using System.Threading.Tasks;
-using ZR.Model;
namespace ZR.Service
{
@@ -138,7 +136,7 @@ namespace ZR.Service
///
///
///
- PagedInfo GetPages(Expression> where, PagerInfo parm);
+ PagedInfo GetPages(Expression> where, Model.PagerInfo parm);
///
/// 根据条件查询分页
@@ -148,7 +146,7 @@ namespace ZR.Service
///
///
///
- PagedInfo GetPages(Expression> where, PagerInfo parm, Expression> order, string orderEnum = "Asc");
+ PagedInfo GetPages(Expression> where, Model.PagerInfo parm, Expression> order, string orderEnum = "Asc");
///
/// 根据条件查询数据
diff --git a/ZR.Service/ZR.Service.csproj b/ZR.Service/ZR.Service.csproj
index 6f3c4d0..a27cb43 100644
--- a/ZR.Service/ZR.Service.csproj
+++ b/ZR.Service/ZR.Service.csproj
@@ -9,4 +9,9 @@
+
+
+
+
+
diff --git a/ZR.Vue/document/t4.tt b/ZR.Vue/document/t4.tt
deleted file mode 100644
index e69de29..0000000
diff --git a/ZR.Vue/document/template.vue b/ZR.Vue/document/template.vue
index 4f7996b..74895c2 100644
--- a/ZR.Vue/document/template.vue
+++ b/ZR.Vue/document/template.vue
@@ -2,9 +2,13 @@
+<<<<<<< HEAD
+=======
+
+>>>>>>> db49575a0ded0eef5e8a68461da1448cdacb3d69
-
+
@@ -16,18 +20,18 @@
-
+
-
+
- 搜索
+ 搜索
重置
@@ -44,13 +48,13 @@
删除
-
+
+
@@ -86,7 +90,7 @@
-
+
@@ -106,7 +110,7 @@
- {{dict.dictLabel}}
+ {{dict.dictLabel}}
@@ -132,23 +136,23 @@ export default {
name: "demo",
data() {
return {
+ labelWidth: "70px",
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 查询参数
- queryParams: {
- useridx: undefined,
- name: undefined,
- },
+ queryParams: {},
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 表单参数
form: {},
+ // 时间范围数组
+ timeRange: [],
// xxx下拉框
- options: [],
+ statusOptions: [],
// 数据列表
dataList: [
{
@@ -170,18 +174,30 @@ export default {
// 表单校验
rules: {
name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
- userId: [{ required: true, message: "id不能为空", trigger: "blur" }],
+ userId: [
+ {
+ type: "number",
+ required: true,
+ message: "id不能为空,且不能为非数字",
+ trigger: "blur",
+ },
+ ],
},
};
},
mounted() {
+ // 列表数据查询
this.getList();
+ // 下拉框绑定
+ // this.getDicts("sys_normal_disable").then((response) => {
+ // this.statusOptions = response.data;
+ // });
},
methods: {
// 查询数据
getList() {
console.log(JSON.stringify(this.queryParams));
- // listXXXX().then(res => {
+ // listXXXX(this.addDateRange(this.queryParams, this.timeRange)).then(res => {
// if (res.code == 200) {
// this.dataList = res.data.result;
// this.total = res.data.totalCount;
@@ -195,7 +211,6 @@ export default {
},
// 重置数据表单
reset() {
- this.btnSubmitVisible = true;
this.form = {
Id: undefined,
// TODO 其他列字段
@@ -204,7 +219,12 @@ export default {
},
/** 重置查询操作 */
resetQuery() {
+ this.timeRange = [];
this.resetForm("queryForm");
+ this.queryParams = {
+ pageNum: 1,
+ //TODO 重置字段
+ };
},
/** 搜索按钮操作 */
handleQuery() {
@@ -222,7 +242,10 @@ export default {
handleDelete(row) {
// delXXX().then((res) => {
// this.msgSuccess("删除成功");
+<<<<<<< HEAD
+=======
+>>>>>>> db49575a0ded0eef5e8a68461da1448cdacb3d69
// this.handleQuery();
// });
},
diff --git a/ZR.Vue/package.json b/ZR.Vue/package.json
index 4b84f42..48dafb0 100644
--- a/ZR.Vue/package.json
+++ b/ZR.Vue/package.json
@@ -21,11 +21,11 @@
},
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
- "axios": "^0.21.1",
+ "axios": "^0.21.4",
"clipboard": "2.0.4",
"core-js": "3.6.5",
"echarts": "^5.1.1",
- "element-ui": "2.13.2",
+ "element-ui": "2.15.6",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"js-beautify": "1.10.2",
diff --git a/ZR.Vue/public/index.html b/ZR.Vue/public/index.html
index 6d64bf9..ad1a290 100644
--- a/ZR.Vue/public/index.html
+++ b/ZR.Vue/public/index.html
@@ -1,13 +1,16 @@
-
-
-
-
-
-
- <%= webpackConfig.name %>
-
-
-
-
-
+
+
+
+