using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Admin.NET.Core; using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Linq.Dynamic.Core; using Microsoft.AspNetCore.Http; using System.Text; using System.Web; using System.ComponentModel; using System.Data; namespace @Model.NameSpace { /// /// @(@Model.BusName)服务 /// [ApiDescriptionSettings("@Model.ModuleName", Name = "@Model.ClassName", Order = 100)] [Route("api")] public class @(@Model.ClassName)Service : I@(@Model.ClassName)Service, IDynamicApiController, ITransient { private readonly IRepository<@(@Model.ClassName),@(@Model.DatabaseName)> _@(@Model.CamelizeClassName)Rep; @foreach (var column in Model.TableField){ if(@column.EffectType == "fk" && @column.FkEntityName != "" && @column.FkColumnName != ""){ @:private readonly IRepository<@(@column.FkEntityName)> _@(@column.LowerFkEntityName)Rep; } } private readonly IRepository _sysDictTypeRep; private readonly IRepository _sysDictDataRep; private readonly ISysExcelTemplateService _sysExcelTemplateService; private readonly static object _lock = new(); @if(@Model.IsFile) { @:private readonly IRepository _sysFileInfoRep; } public @(@Model.ClassName)Service( @foreach (var column in Model.TableField){ if(@column.EffectType == "fk" && @column.FkEntityName != "" && @column.FkColumnName != ""){ @:IRepository<@(@column.FkEntityName)> @(@column.LowerFkEntityName)Rep, } } IRepository<@(@Model.ClassName),@(@Model.DatabaseName)> @(@Model.CamelizeClassName)Rep @if(@Model.IsFile) { @:,IRepository sysFileInfoRep, } ,IRepository sysDictTypeRep ,IRepository sysDictDataRep ,ISysExcelTemplateService sysExcelTemplateService ) { @foreach (var column in Model.TableField){ if(@column.EffectType == "fk" && @column.FkEntityName != "" && @column.FkColumnName != ""){ @:_@(@column.LowerFkEntityName)Rep = @(@column.LowerFkEntityName)Rep; } } _@(@Model.CamelizeClassName)Rep = @(@Model.CamelizeClassName)Rep; @if(@Model.IsFile) { @:_sysFileInfoRep = sysFileInfoRep; } _sysDictTypeRep = sysDictTypeRep; _sysDictDataRep = sysDictDataRep; _sysExcelTemplateService = sysExcelTemplateService; } /// /// 分页查询@(@Model.BusName) /// /// /// [HttpGet("@Model.ClassName/page")] public async Task> Page([FromQuery] @(@Model.ClassName)Search input) { var @(@Model.CamelizeClassName)s = await _@(@Model.CamelizeClassName)Rep.DetachedEntities @foreach (var column in Model.TableField){ if (@column.QueryWhether == "Y"){ if (@column.NetType == "string"){ if (@column.QueryType == "like"){ @:.Where(!string.IsNullOrEmpty(input.@column.ColumnName), u => EF.Functions.Like(u.@(@column.ColumnName), $"%{input.@(@column.ColumnName).Trim()}%")) } else { @:.Where(!string.IsNullOrEmpty(input.@column.ColumnName), u => u.@(@column.ColumnName) @column.QueryType input.@(@column.ColumnName)) } } else { if (@column.EffectType == "fk"){ @:.Where(input.@column.ColumnName > 0, u => u.@(@column.ColumnName) @column.QueryType input.@(@column.ColumnName)) } if (@column.EffectType == "datepicker" && @column.QueryType == "between"){ @:.Where(input.@column.ColumnName!=null, u => u.@(@column.ColumnName)>= Convert.ToDateTime(input.@(@column.ColumnName)[0]+" 00:00:00") && u.@(@column.ColumnName)<= Convert.ToDateTime(input.@(@column.ColumnName)[1]+" 23:59:59")) } else if (@column.EffectType == "datetimepicker" && @column.QueryType == "between"){ @:.Where(input.@column.ColumnName!=null, u => u.@(@column.ColumnName)>= Convert.ToDateTime(input.@(@column.ColumnName)[0]) && u.@(@column.ColumnName)<= Convert.ToDateTime(input.@(@column.ColumnName)[1])) } else { @:.Where(input.@column.ColumnName != null, u => u.@(@column.ColumnName) @column.QueryType input.@(@column.ColumnName)) } } } } .OrderBy(PageInputOrder.OrderBuilder<@(@Model.ClassName)Search>(input)) .ProjectToType<@(@Model.ClassName)Output>() .ToADPagedListAsync(input.PageNo, input.PageSize); @if(@Model.IsFile) { @:@(@Model.CamelizeClassName)s.Rows.ToList().ForEach(item => @:{ foreach (var column in Model.FileTableField){ @:item.@(@column.ColumnName) = item.@(@column.ColumnName)_Str.GetFiles(_sysFileInfoRep); } @:}); } return @(@Model.CamelizeClassName)s; } /// /// 不分页查询@(@Model.BusName)列表 /// /// @(@Model.BusName)查询参数 /// (@Model.BusName)实例列表 [HttpGet("@Model.ClassName/listNonPage")] public async Task> ListNonPageAsync([FromQuery] @(@Model.ClassName)SearchNonPage input) { @foreach (var column in Model.TableField) { if (@column.QueryWhether == "Y") { if(@column.NetType == "string" && @column.QueryType != "isNotNull"){ @:var p@(@column.ColumnName) = input.@(@column.ColumnName)?.Trim() ?? ""; } else if(@column.QueryType != "isNotNull"){ @:var p@(@column.ColumnName) = input.@(@column.ColumnName); } } } var @(@Model.CamelizeClassName)s = await _@(@Model.CamelizeClassName)Rep.DetachedEntities @foreach (var column in Model.TableField) { if (@column.QueryWhether == "Y") { if(@column.QueryType == "isNotNull") { @:.Where(u => u.@(@column.ColumnName) != null) } else if (@column.NetType == "string") { if (@column.QueryType == "like") { @:.Where(!string.IsNullOrEmpty(p@(@column.ColumnName)), u => EF.Functions.Like(u.@(@column.ColumnName), $"%{p@(@column.ColumnName)}%")) } else { @:.Where(!string.IsNullOrEmpty(p@(@column.ColumnName)), u => u.@(@column.ColumnName) @column.QueryType p@(@column.ColumnName)) } } else if (@column.EffectType == "datepicker"&&@column.QueryType == "between") { @:.Where(input.@column.ColumnName!=null, u => u.@(@column.ColumnName)>= Convert.ToDateTime(input.@(@column.ColumnName)[0]+" 00:00:00") && u.@(@column.ColumnName)<= Convert.ToDateTime(input.@(@column.ColumnName)[1]+" 23:59:59")) } else if (@column.EffectType == "datetimepicker" && @column.QueryType == "between"){ @:.Where(input.@column.ColumnName!=null, u => u.@(@column.ColumnName)>= Convert.ToDateTime(input.@(@column.ColumnName)[0]) && u.@(@column.ColumnName)<= Convert.ToDateTime(input.@(@column.ColumnName)[1])) }else if (@column.EffectType == "fk") { @:.Where(p@(@column.ColumnName) > 0, u => u.@(@column.ColumnName) @column.QueryType p@(@column.ColumnName)) } else { @:.Where(p@(@column.ColumnName) != null, u => u.@(@column.ColumnName) @column.QueryType p@(@column.ColumnName)) } } } .OrderBy(PageInputOrder.OrderNonPageBuilder(input)) .ProjectToType<@(@Model.ClassName)Output>() .ToListAsync(); @if(@Model.IsFile) { @:@(@Model.CamelizeClassName)s.ForEach(item => @:{ foreach (var column in Model.FileTableField){ @:item.@(@column.ColumnName) = item.@(@column.ColumnName)_Str.GetFiles(_sysFileInfoRep); } @:}); } return @(@Model.CamelizeClassName)s; } /// /// 获取@(@Model.BusName) /// /// /// [HttpGet("@Model.ClassName/detail")] public async Task<@(@Model.ClassName)Output> Get([FromQuery] Querye@(@Model.ClassName)Input input) { @foreach (var column in Model.TableField){ if (@column.ColumnKey == "True"){ @:return (await _@(@Model.CamelizeClassName)Rep.DetachedEntities.FirstOrDefaultAsync(u => u.@(@column.ColumnName) == input.@(@column.ColumnName))).Adapt<@(@Model.ClassName)Output>(); }else{ if (@Model.IsOnlyQuery == true){ @:return null; } } } } /// /// 获取@(@Model.BusName)列表 /// /// /// [HttpGet("@Model.ClassName/list")] public async Task> List([FromQuery] @(@Model.ClassName)Input input) { return await _@(@Model.CamelizeClassName)Rep.DetachedEntities.ProjectToType<@(@Model.ClassName)Output>().ToListAsync(); } @foreach (var column in Model.TableField){ if(@column.EffectType == "fk" && @column.FkEntityName != "" && @column.FkColumnName != ""){ @: @:/// @:/// 获取@(@column.FkEntityName)列表 @:/// @:/// @:[HttpGet("fk@(@column.FkEntityName)")] @:public async Task Fk@(@column.FkEntityName)List() @:{ @:var list = await _@(@column.LowerFkEntityName)Rep.DetachedEntities.ToListAsync(); @:return list.Select(e => new {Code = e.Id, Name = e.@(@column.FkColumnName)}); @:} } } #region 增、删、改 /// /// 增加@(@Model.BusName) /// /// /// [HttpPost("@Model.ClassName/add")] public async Task Add(Add@(@Model.ClassName)Input input) { var @(@Model.CamelizeClassName) = input.Adapt<@(@Model.ClassName)>(); //验证 await CheckExisit(@(@Model.CamelizeClassName)); @(@Model.CamelizeClassName).CreatedUserId = @(@Model.CamelizeClassName).UpdatedUserId = SysHelper.GetUserId(); @(@Model.CamelizeClassName).CreatedUserName = @(@Model.CamelizeClassName).UpdatedUserName = SysHelper.GetUserName(); @(@Model.CamelizeClassName).CreatedTime = @(@Model.CamelizeClassName).UpdatedTime = SysHelper.GetNowTime(); await _@(@Model.CamelizeClassName)Rep.InsertAsync(@(@Model.CamelizeClassName)); } /// /// 删除@(@Model.BusName) /// /// /// [HttpPost("@Model.ClassName/delete")] public async Task Delete(Delete@(@Model.ClassName)Input input) { @foreach (var column in Model.TableField){ if (@column.ColumnKey == "True"){ @:var @(@Model.CamelizeClassName) = await _@(@Model.CamelizeClassName)Rep.FirstOrDefaultAsync(u => u.@(@column.ColumnName) == input.@(@column.ColumnName)); @:await _@(@Model.CamelizeClassName)Rep.DeleteAsync(@(@Model.CamelizeClassName)); } } } /// /// 更新@(@Model.BusName) /// /// /// [HttpPost("@Model.ClassName/edit")] public async Task Update(Update@(@Model.ClassName)Input input) { var isExist = await _@(@Model.CamelizeClassName)Rep.AnyAsync(u => u.Id == input.Id, false); if (!isExist) throw Oops.Oh(ErrorCode.D1002); var @(@Model.CamelizeClassName) = input.Adapt<@(@Model.ClassName)>(); //验证 await CheckExisit(@(@Model.CamelizeClassName),true); @(@Model.CamelizeClassName).UpdatedUserId = SysHelper.GetUserId(); @(@Model.CamelizeClassName).UpdatedUserName = SysHelper.GetUserName(); @(@Model.CamelizeClassName).UpdatedTime = SysHelper.GetNowTime(); await _@(@Model.CamelizeClassName)Rep.UpdateAsync(@(@Model.CamelizeClassName),ignoreNullValues:true); } #endregion #region 导入 /// /// Excel模板导入@(@Model.BusName)功能 /// /// Excel模板文件 /// 导入的记录数 [HttpPost("@Model.ClassName/importExcel")] public async Task ImportExcelAsync(IFormFile file) { int _HeadStartLine = 2;//第1行是说明,第2行是列名 int _DataStartLine = 3;//第3行开始是数据 DataTable importDataTable = ExcelUtil.ImportExcelToDataTable(file, _HeadStartLine, _DataStartLine); var addList =await CommonImport(importDataTable, _DataStartLine); lock (_lock) { _@(@Model.CamelizeClassName)Rep.InsertAsync(addList); } await Task.CompletedTask; return addList.Count; } /// /// DataTable转换实体对象列表 /// /// /// 模版列名开始行 /// private async Task> CommonImport(DataTable dataTable, int dataStartLine) { var details = new List<@(@Model.ClassName)>(); int index = dataStartLine;//模版列名开始行 foreach (System.Data.DataRow row in dataTable.Rows) { index++; //导入模版定制化代码(替换模版使用) @Model.ImportExcelCustomizationContent details.Add(addItem); } //验重 await CheckExisitForImport(details); return details; } /// /// 根据版本下载@(@Model.BusName)的Excel导入模板 /// /// 模板版本 /// 下载的模板文件 [HttpGet("@Model.ClassName/downloadExcelTemplate")] public IActionResult DownloadExcelTemplate([FromQuery] string version) { string _path = TemplateConst.EXCEL_TEMPLATEFILE_导入模版路径 + $"\\@Model.ClassName{TemplateConst.EXCEL_TEMPLATEFILE_导入模版名称后缀}.xlsx"; var fileName = HttpUtility.UrlEncode($"导入模板(@Model.BusName).xlsx", Encoding.GetEncoding("UTF-8")); return new FileStreamResult(new FileStream(_path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName }; } #endregion #region 私有方法 /// /// 根据联合主键验证数据是否已存在-数据库 /// /// /// /// private async Task CheckExisit( @(@Model.ClassName) input,bool isEdit=false) { @{ var columnIndex = 0; } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { columnIndex++; if (@columnIndex == 1) { @:bool isExist = false; @:if (!isEdit)//新增 @:{ @://数据是否存在重复 @:isExist = await _@(@Model.CamelizeClassName)Rep.AnyAsync(u => @:u.@(@column.ColumnName).Equals(input.@column.ColumnName) } else { @:&&u.@(@column.ColumnName).Equals(input.@column.ColumnName) } } } @if(columnIndex>0){ @:,false); @:} @:else//编辑 @:{ } @{ columnIndex=0;//初始化索引 下面编辑的逻辑使用 } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { columnIndex++; if (@columnIndex == 1) { @://当前编辑数据以外是否存在重复 @: isExist = await _@(@Model.CamelizeClassName)Rep.AnyAsync(u => @:u.Id != input.Id @:&&u.@(@column.ColumnName).Equals(input.@column.ColumnName) } else { @:&&u.@(@column.ColumnName).Equals(input.@column.ColumnName) } } } @if(columnIndex>0) { @:,false); @:} } @if(columnIndex>0){ @:if (isExist) throw Oops.Oh(ErrorCode.E0001); }else{ @://没有配置联合主键,不需要验重 } } /// /// 根据联合主键验证数据是否已存在-导入时验证 /// /// /// private async Task CheckExisitForImport(List<@(@Model.ClassName)> inputs) { //根据联合主键验证表格中中是否已存在相同数据 @{ var index = 0; bool isCheck = false; string message = string.Empty; } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { isCheck = true; message += "," + @column.ColumnComment + "[{item." + @column.ColumnName + "}]"; } } @if (isCheck) { @:if (inputs?.Count <= 0) @:{ @: throw Oops.Oh($"导入数据不能为空"); @:} @://数据是否重复 @:var existExcelItem = inputs.GroupBy(g => new { } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { index++; if (@index == 1) { @:g.@(@column.ColumnName) } else { @:,g.@(@column.ColumnName) } } } @if (isCheck) { index=0; @:}) @:.Where(g => g.Count() > 1) @:.Select(s => new { } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { index++; if (@index == 1) { @:s.Key.@(@column.ColumnName) } else { @:,s.Key.@(@column.ColumnName) } } } @if (isCheck) { @:}).FirstOrDefault(); @:if (existExcelItem != null) @:{ @:var item= existExcelItem.Adapt<@(@Model.ClassName)>(); @:throw Oops.Oh($"导入的表格中@(@message)已存在"); @:} } @if (isCheck) { @://根据联合主键验证数据库中是否已存在相同数据 @:var existDBItem = await _@(@Model.CamelizeClassName)Rep.DetachedEntities.FirstOrDefaultAsync(w=> @: inputs.Select(s=>"" } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { @: +s.@(@column.ColumnName) } } @if (isCheck) { @:) @:.Contains("" } @foreach (var column in Model.TableField) { if (@column.WhetherUnionKey == "Y") { @: +w.@(@column.ColumnName) } } @if (isCheck) { @: )); @: if (existDBItem != null) @:{ @:var item= existDBItem.Adapt<@(@Model.ClassName)>(); @:throw Oops.Oh($"系统中@(@message)已存在"); @:} } } #endregion } }