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
|
{
|
/// <summary>
|
/// @(@Model.BusName)服务
|
/// </summary>
|
[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<SysDictType, MasterDbContextLocator> _sysDictTypeRep;
|
private readonly IRepository<SysDictData, MasterDbContextLocator> _sysDictDataRep;
|
private readonly ISysExcelTemplateService _sysExcelTemplateService;
|
private readonly static object _lock = new();
|
@if(@Model.IsFile)
|
{
|
@:private readonly IRepository<SysFile> _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<SysFile> sysFileInfoRep,
|
}
|
,IRepository<SysDictType, @(@Model.DatabaseName)> sysDictTypeRep
|
,IRepository<SysDictData, @(@Model.DatabaseName)> 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;
|
}
|
|
/// <summary>
|
/// 分页查询@(@Model.BusName)
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpGet("@Model.ClassName/page")]
|
public async Task<PageResult<@(@Model.ClassName)Output>> 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;
|
}
|
|
/// <summary>
|
/// 不分页查询@(@Model.BusName)列表
|
/// </summary>
|
/// <param name="input">@(@Model.BusName)查询参数</param>
|
/// <returns>(@Model.BusName)实例列表</returns>
|
[HttpGet("@Model.ClassName/listNonPage")]
|
public async Task<List<@(@Model.ClassName)Output>> 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;
|
}
|
|
/// <summary>
|
/// 获取单个@(@Model.BusName)
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpGet("@Model.ClassName/detail")]
|
public async Task<@(@Model.ClassName)Output> Get([FromQuery] Querye@(@Model.ClassName)Input input)
|
{
|
return (await _@(@Model.CamelizeClassName)Rep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id)).Adapt<@(@Model.ClassName)Output>();
|
}
|
|
/// <summary>
|
/// 获取@(@Model.BusName)列表
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpGet("@Model.ClassName/list")]
|
public async Task<List<@(@Model.ClassName)Output>> 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 != ""){
|
@:
|
@:/// <summary>
|
@:/// 获取@(@column.FkEntityName)列表
|
@:/// </summary>
|
@:/// <returns></returns>
|
@:[HttpGet("fk@(@column.FkEntityName)")]
|
@:public async Task<dynamic> 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 增、删、改
|
|
/// <summary>
|
/// 增加@(@Model.BusName)
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[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));
|
}
|
|
/// <summary>
|
/// 删除@(@Model.BusName)
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[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));
|
}
|
}
|
|
}
|
|
/// <summary>
|
/// 更新@(@Model.BusName)
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[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 导入
|
|
/// <summary>
|
/// Excel模板导入@(@Model.BusName)功能
|
/// </summary>
|
/// <param name="file">Excel模板文件</param>
|
/// <returns>导入的记录数</returns>
|
[HttpPost("@Model.ClassName/importExcel")]
|
public async Task<int> 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;
|
}
|
|
/// <summary>
|
/// DataTable转换实体对象列表
|
/// </summary>
|
/// <param name="dataTable"></param>
|
/// <param name="dataStartLine">模版列名开始行</param>
|
/// <returns></returns>
|
private async Task<List<@(@Model.ClassName)>> 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;
|
}
|
|
/// <summary>
|
/// 根据版本下载@(@Model.BusName)的Excel导入模板
|
/// </summary>
|
/// <param name="version">模板版本</param>
|
/// <returns>下载的模板文件</returns>
|
[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 私有方法
|
|
/// <summary>
|
/// 根据联合主键验证数据是否已存在-数据库
|
/// </summary>
|
/// <param name="input"></param>
|
/// <param name="isEdit"></param>
|
/// <returns></returns>
|
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{
|
@://没有配置联合主键,不需要验重
|
}
|
}
|
|
/// <summary>
|
/// 根据联合主键验证数据是否已存在-导入时验证
|
/// </summary>
|
/// <param name="inputs"></param>
|
/// <returns></returns>
|
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
|
}
|
}
|