using JNPF.Common.Configuration; using JNPF.Common.Core.Manager; using JNPF.Common.Core.Manager.Files; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Filter; using JNPF.Common.Models.NPOI; using JNPF.Common.Security; using JNPF.DataEncryption; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.VisualDev.Engine; using JNPF.VisualDev.Engine.Core; using JNPF.VisualDev.Entitys; using JNPF.VisualDev.Entitys.Dto.VisualDevModelData; using JNPF.VisualDev.Interfaces; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace JNPF.VisualDev; /// /// 可视化开发APP基础. /// [ApiDescriptionSettings(Tag = "VisualDev", Name = "App", Order = 175)] [Route("api/visualdev/OnlineDev/[controller]")] public class VisualdevModelAppService : IDynamicApiController, ITransient { /// /// 可视化开发基础. /// private readonly IVisualDevService _visualDevService; /// /// 在线开发运行服务. /// private readonly IRunService _runService; /// /// 用户管理. /// private readonly IUserManager _userManager; /// /// 文件服务. /// private readonly IFileManager _fileManager; /// /// 初始化一个类型的新实例. /// public VisualdevModelAppService( IVisualDevService visualDevService, IRunService runService, IUserManager userManager, IFileManager fileManager) { _visualDevService = visualDevService; _runService = runService; _userManager = userManager; _fileManager = fileManager; } #region Get /// /// 获取列表表单配置JSON. /// /// 主键id. /// 1 线上版本, 0 草稿版本. /// [HttpGet("{modelId}/Config")] [NonUnify] public async Task GetData(string modelId, string type) { if (type.IsNullOrEmpty()) type = "1"; VisualDevEntity? data = await _visualDevService.GetInfoById(modelId, type.Equals("1")); if (data == null) return new { code = 400, msg = "未找到该模板!" }; if (data.EnableFlow.Equals(1) && data.FlowId.IsNullOrWhiteSpace()) return new { code = 400, msg = "该流程功能未绑定流程!" }; if (data.WebType.Equals(1) && data.FormData.IsNullOrWhiteSpace()) return new { code = 400, msg = "该模板内表单内容为空,无法预览!" }; else if (data.WebType.Equals(2) && data.ColumnData.IsNullOrWhiteSpace()) return new { code = 400, msg = "该模板内列表内容为空,无法预览!" }; return new { code = 200, data = data.Adapt() }; } /// /// 获取列表配置JSON. /// /// 主键id. /// [HttpGet("{modelId}/ColumnData")] public async Task GetColumnData(string modelId) { VisualDevEntity? data = await _visualDevService.GetInfoById(modelId); return new { columnData = data.ColumnData }; } /// /// 获取列表配置JSON. /// /// 主键id. /// [HttpGet("{modelId}/FormData")] public async Task GetFormData(string modelId) { VisualDevEntity? data = await _visualDevService.GetInfoById(modelId); return new { formData = data.FormData }; } /// /// 获取列表配置JSON. /// /// 主键id. /// [HttpGet("{modelId}/FlowTemplate")] public async Task GetFlowTemplate(string modelId) { VisualDevEntity? data = await _visualDevService.GetInfoById(modelId); return new { flowTemplateJson = data.FlowTemplateJson }; } /// /// 获取数据信息. /// /// /// /// [HttpGet("{modelId}/{id}")] public async Task GetInfo(string id, string modelId) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); // 模板实体 if (!string.IsNullOrEmpty(templateEntity.Tables) && !"[]".Equals(templateEntity.Tables)) return new { id = id, data = (await _runService.GetHaveTableInfo(id, templateEntity)).ToJsonString() }; // 有表 else return null; } /// /// 获取详情. /// /// /// /// [HttpGet("{modelId}/{id}/DataChange")] public async Task GetDetails(string id, string modelId) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); // 模板实体 if (!string.IsNullOrEmpty(templateEntity.Tables) && !"[]".Equals(templateEntity.Tables)) return new { id = id, data = await _runService.GetHaveTableInfoDetails(id, templateEntity) }; // 有表 else return null; } #endregion #region Post /// /// 功能导出. /// /// /// [HttpPost("{modelId}/Actions/ExportData")] public async Task ActionsExportData(string modelId) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId); // 模板实体 if (templateEntity.State.Equals(1)) { var vREntity = await _visualDevService.GetInfoById(modelId, true); templateEntity = vREntity.Adapt(); templateEntity.State = 0; } string? jsonStr = templateEntity.ToJsonString(); return await _fileManager.Export(jsonStr, templateEntity.FullName, ExportFileType.va); } /// /// 导入. /// /// /// [HttpPost("Model/Actions/ImportData")] public async Task ActionsActionsImport(IFormFile file) { string? fileType = Path.GetExtension(file.FileName).Replace(".", string.Empty); if (!fileType.ToLower().Equals(ExportFileType.va.ToString())) throw Oops.Oh(ErrorCode.D3006); string? josn = _fileManager.Import(file); VisualDevEntity? templateEntity; try { templateEntity = josn.ToObject(); } catch { throw Oops.Oh(ErrorCode.D3006); } if (templateEntity == null || templateEntity.Type.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.D3006); else if (templateEntity.Type != 2) throw Oops.Oh(ErrorCode.D3009); if (await _visualDevService.GetDataExists(templateEntity.EnCode, templateEntity.FullName)) throw Oops.Oh(ErrorCode.D1400); await _visualDevService.CreateImportData(templateEntity); } /// /// 获取数据列表. /// /// 主键id. /// 分页查询条件. /// [HttpPost("{modelId}/List")] public async Task List(string modelId, [FromBody] VisualDevModelListQueryInput input) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); return await _runService.GetListResult(templateEntity, input); } /// /// 创建数据. /// /// /// /// [HttpPost("{modelId}")] public async Task Create(string modelId, [FromBody] VisualDevModelDataCrInput visualdevModelDataCrForm) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); await _runService.Create(templateEntity, visualdevModelDataCrForm); } /// /// 修改数据. /// /// /// /// /// [HttpPut("{modelId}/{id}")] public async Task Update(string modelId, string id, [FromBody] VisualDevModelDataUpInput visualdevModelDataUpForm) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); await _runService.Update(id, templateEntity, visualdevModelDataUpForm); } /// /// 删除数据. /// /// /// /// [HttpDelete("{modelId}/{id}")] public async Task Delete(string id, string modelId) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); if (!string.IsNullOrEmpty(templateEntity.Tables) && !"[]".Equals(templateEntity.Tables)) await _runService.DelHaveTableInfo(id, templateEntity); } /// /// 批量删除. /// /// /// /// [HttpPost("batchDelete/{modelId}")] public async Task BatchDelete(string modelId, [FromBody] VisualDevModelDataBatchDelInput input) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); if (!string.IsNullOrEmpty(templateEntity.Tables) && !"[]".Equals(templateEntity.Tables)) await _runService.BatchDelHaveTableData(input.ids, templateEntity); } /// /// 导出. /// /// [HttpPost("{modelId}/Actions/Export")] public async Task Export(string modelId, [FromBody] VisualDevModelListQueryInput input) { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(modelId, true); PageResult>? pageList = await _runService.GetListResult(templateEntity, input); #region 如果是 分组表格 模板 ColumnDesignModel? ColumnData = templateEntity.ColumnData.ToObject(); // 列配置模型 if (ColumnData.type == 3) { List>? newValueList = new List>(); pageList.list.ForEach(item => { List>? tt = item["children"].ToJsonString().ToObject>>(); newValueList.AddRange(tt); }); pageList.list = newValueList; } #endregion List> realList = pageList.list.Copy(); var templateInfo = new TemplateParsingBase(templateEntity); var res = GetCreateFirstColumnsHeader(input.selectKey, realList, templateInfo); var firstColumns = res.First().ToObject>(); var resultList = res.Last().ToObject>>(); var newResultList = new List>(); resultList.ForEach(row => { foreach (var item in input.selectKey) { if (row[item].IsNotEmptyOrNull()) { newResultList.Add(row); break; } } }); return firstColumns.Any() ? await ExcelCreateModel(templateInfo, resultList, input.selectKey, null, firstColumns) : await ExcelCreateModel(templateInfo, resultList, input.selectKey); } #endregion #region PublicMethod /// /// Excel 转输出 Model. /// /// 模板. /// 数据列表. /// /// 导出文件名称. /// 手动输入第一行(合并主表列和各个子表列). /// VisualDevModelDataExportOutput. public async Task ExcelCreateModel(TemplateParsingBase templateInfo, List> realList, List keys, string excelName = null, Dictionary firstColumns = null) { List templateList = new List(); VisualDevModelDataExportOutput output = new VisualDevModelDataExportOutput(); List columnList = new List(); try { ExcelConfig excelconfig = new ExcelConfig(); excelconfig.FileName = (excelName.IsNullOrEmpty() ? SnowflakeIdHelper.NextId() : excelName) + ".xls"; excelconfig.HeadFont = "微软雅黑"; excelconfig.HeadPoint = 10; excelconfig.IsAllSizeColumn = true; excelconfig.ColumnModel = new List(); foreach (string? item in keys) { FieldsModel? excelColumn = templateInfo.AllFieldsModel.Find(t => t.__vModel__ == item); if (excelColumn != null) { excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = item, ExcelColumn = excelColumn.__config__.label }); columnList.Add(excelColumn.__config__.label); } } string? addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName); var fs = firstColumns == null ? ExcelExportHelper>.ExportMemoryStream(realList, excelconfig, columnList) : ExcelExportHelper>.ExportMemoryStream(realList, excelconfig, columnList, firstColumns); var flag = await _fileManager.UploadFileByType(fs, FileVariable.TemporaryFilePath, excelconfig.FileName); if (flag) { fs.Flush(); fs.Close(); } output.name = excelconfig.FileName; output.url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|" + excelconfig.FileName + "|" + addPath, "JNPF"); return output; } catch (Exception) { throw; } } /// /// 组装导出带子表得数据,返回 第一个合并行标头,第二个导出数据. /// /// 导出选择列. /// 原数据集合. /// 模板信息. /// 第一行标头 , 导出数据. public object[] GetCreateFirstColumnsHeader(List selectKey, List> realList, TemplateParsingBase templateInfo) { selectKey.ForEach(item => { realList.ForEach(it => { if (!it.ContainsKey(item)) it.Add(item, string.Empty); }); }); var newRealList = realList.Copy(); realList.ForEach(items => { var rowChildDatas = new Dictionary>>(); foreach (var item in items) { if (item.Value != null && item.Key.ToLower().Contains("tablefield") && item.Value is List>) { var ctList = item.Value.ToObject>>(); rowChildDatas.Add(item.Key, ctList); } } var len = rowChildDatas.Select(x => x.Value.Count()).OrderByDescending(x => x).FirstOrDefault(); if (len != null && len > 0) { for (int i = 0; i < len; i++) { if (i == 0) { var newRealItem = newRealList.Find(x => x["id"].Equals(items["id"])); foreach (var cData in rowChildDatas) { var itemData = cData.Value.FirstOrDefault(); if (itemData != null) { foreach (var key in itemData) if (newRealItem.ContainsKey(cData.Key + "-" + key.Key)) newRealItem[cData.Key + "-" + key.Key] = key.Value; } } } else { var newRealItem = new Dictionary(); foreach (var it in items) { if (it.Key.Equals("id")) newRealItem.Add(it.Key, it.Value); else newRealItem.Add(it.Key, string.Empty); } foreach (var cData in rowChildDatas) { if (cData.Value.Count > i) { foreach (var it in cData.Value[i]) if (newRealItem.ContainsKey(cData.Key + "-" + it.Key)) newRealItem[cData.Key + "-" + it.Key] = it.Value; } } newRealList.Add(newRealItem); } } } }); var resultList = new List>(); newRealList.ForEach(newRealItem => { if (!resultList.Any(x => x["id"].Equals(newRealItem["id"]))) resultList.AddRange(newRealList.Where(x => x["id"].Equals(newRealItem["id"])).ToList()); }); var firstColumns = new Dictionary(); if (selectKey.Any(x => x.Contains("-") && x.Contains("tableField"))) { var empty = string.Empty; var keyList = selectKey.Select(x => x.Split("-").First()).Distinct().ToList(); var mainFieldIndex = 1; keyList.ForEach(item => { if (item.Contains("tableField")) { var title = templateInfo.AllFieldsModel.FirstOrDefault(x => x.__vModel__.Equals(item))?.__config__.label; firstColumns.Add(title + empty, selectKey.Count(x => x.Contains(item))); empty += " "; mainFieldIndex = 1; } else { if (mainFieldIndex == 1) empty += " "; if (!firstColumns.ContainsKey(empty)) firstColumns.Add(empty, mainFieldIndex); else firstColumns[empty] = mainFieldIndex; mainFieldIndex++; } }); } return new object[] { firstColumns, resultList }; } #endregion }