using Mds.Contracts.Customization;
using Mds.Customization.Entities;
using Mds.Customization.Repositories;
using Mds.Enums.Customization;
using Mds.Extention;
using Mds.Master.Customer;
using Mds.Master.Entities;
using Mds.Som.ChargePriceAdjust;
using Mds.Som.ChargePriceAdjustItem;
using Mds.Som.Entities;
using Mds.Toolkit;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Minio.DataModel.Notification;
using Modern.Toolkits.Dtos;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
namespace Mds.Customization
{
//[Authorize]
public class CustSearchAppService : MdsCustCrudAppService
<SearchEntity, SearchDto, Dictionary<string, object>, Guid, PagedAndFilterResultRequestDto, CreateOrUpdateSearchDto, CreateOrUpdateSearchDto>,
ICustSearchAppService
{
private readonly ILogger<CustSearchAppService> _logger;
private readonly ISearchRepository _searchRepository;
private readonly IRecordTypeRepository _recordTypeRepository;
private readonly ICustRecordTypeFieldAppService _recordTypeFieldAppService;
private readonly IRecordTypeFieldFilterSourceListRepository _recordFieldFilterSourceListRepository;
private readonly ISearchAvailableFilterRepository _searchAvailableFilterRepository;
private readonly ISearchCriteriaRepository _searchCriteriaRepository;
private readonly ISearchResultRepository _searchResultRepository;
private readonly IRecordTypeFieldRepository _recordTypeFieldRepository;
public CustSearchAppService(
IHttpClientFactory httpClientFactory,
IRepository<SearchEntity, Guid> repository,
ILogger<CustSearchAppService> logger,
IHttpContextAccessor httpContextAccessor,
ISearchRepository searchRepository,
ISearchCriteriaRepository searchCriteriaRepository,
ISearchAvailableFilterRepository searchAvailableFilterRepository,
IRecordTypeRepository recordTypeRepository,
IRecordTypeFieldRepository recordFieldRepository,
IFieldRepository fieldRepository,
ICustFieldAppService fieldAppService,
ICustRecordTypeFieldAppService recordTypeFieldAppService,
IRecordTypeFieldFilterSourceListRepository recordTypeFieldFilterSourceListRepository
,
ISearchResultRepository searchResultRepository,
IRecordTypeFieldRepository recordTypeFieldRepository) : base(repository)
{
_logger = logger;
_searchRepository = searchRepository;
_recordTypeRepository = recordTypeRepository;
_recordTypeFieldAppService = recordTypeFieldAppService;
_recordFieldFilterSourceListRepository = recordTypeFieldFilterSourceListRepository;
_searchAvailableFilterRepository = searchAvailableFilterRepository;
_searchCriteriaRepository = searchCriteriaRepository;
_searchResultRepository = searchResultRepository;
_recordTypeFieldRepository = recordTypeFieldRepository;
}
public async override Task<SearchDto> GetAsync(Guid id)
{
var entity = await _searchRepository.FindAsync(id); //.GetAsync(id);
if (entity == null)
{
var recordType = await _recordTypeRepository.GetAsync(id);
entity = ObjectMapper.Map<RecordTypeEntity, SearchEntity>(recordType);
}
var dto = ObjectMapper.Map<SearchEntity, SearchDto>(entity);
var fields = await _GetFieldDtosAsync(entity);
foreach (var item in dto.SearchResults)
{
var field = fields.FirstOrDefault(x => x.Id == item.FieldId);
item.FieldCustomId = field.CustomId;
item.FieldName = field.Name;
item.field = field;
if (item.LinkFieldId.HasValue && item.LinkFieldId != Guid.Empty)
{
var linkField = fields.FirstOrDefault(x => x.Id == item.LinkFieldId);
item.FieldCustomId = field.CustomId + "." + linkField.CustomId;
item.FieldName = linkField.Name;
item.field = Newtonsoft.Json.JsonConvert.DeserializeObject<RecordTypeFieldDto>(Newtonsoft.Json.JsonConvert.SerializeObject(linkField));
item.field.FieldCustomId = item.FieldCustomId;
item.field.Name = item.FieldName;
}
item.RecordTypeId = entity.RecordTypeId;
}
var searchAvailableFilterDtos = await _GetSearchAvailableFilterDtos(fields, entity);
dto.SearchAvailableFilters = searchAvailableFilterDtos;
foreach (var item in dto.SearchAvailableFilters)
{
item.RecordTypeId = entity.RecordTypeId;
}
foreach (var item in dto.SearchCriterias)
{
item.RecordTypeId = entity.RecordTypeId;
Guid filter = new Guid();
if (Guid.TryParse(item.Filter, out filter))
{
var fieldInfo = fields.FirstOrDefault(o => o.Id == Guid.Parse(item.Filter));
item.FilterOptionLabelFields = fieldInfo.OptionLabelFields;
item.FilterFieldListOrRecordTypeId = fieldInfo.FieldListOrRecordTypeId;
}
}
return dto;
}
public async Task<object> GetSearchResultsAsync(Guid id, FilterSearchResultRequestDto input)
{
var search = await _searchRepository.FindAsync(id);
RecordTypeEntity recordType = null;
if (search == null)
{
recordType = await _recordTypeRepository.GetAsync(id);
search = ObjectMapper.Map<RecordTypeEntity, SearchEntity>(recordType);
}
if (recordType == null) recordType = await _recordTypeRepository.GetAsync(search.RecordTypeId);
var fieldDtos = await _GetFieldDtosAsync(search);
var searchResultDtos = await _GetSearchResultDto(fieldDtos, search);
var methdorNameUri = ReplaceMethodNamePlaceholders(recordType.MethodName, input);
input.Filter = await _GetFilterAsync(input, search, recordType, searchResultDtos);
var result = await _fetchRemoteDataAsync(recordType, input, methdorNameUri);
List<dynamic> resultItems = result.Items; // CamelCaseHelper.ToCamelCaseList(result.Items);
if (recordType.IsList)
{
List<ListLineDto> dyList = new List<ListLineDto>();
foreach (var item in resultItems)
{
JObject jObject = JObject.FromObject(item);
var dto = jObject.ToObject<ListLineDto>();
dyList.Add(dto);
}
var pageResult = new PagedResultDto<ListLineDto>() { TotalCount = result.TotalCount, Items = dyList };
return pageResult;
}
ProvideAdditionalInfo(resultItems, searchResultDtos, 0);
if (recordType.CustomId == "history") await RepalceHistoryValueAsync(resultItems, input.RecordTypeId.Value);
if (recordType.CustomId == "record-type-field-filter-source-list")
await ProvidefilterSourceListInfoAsync(resultItems,searchResultDtos);
List<object> list = new List<object>();
// 1. 构建对象
var propertyTypes = GetPropertyTypes(searchResultDtos);
var dyResult = ReflectionHelper.CreateDynamicType("dyResult", propertyTypes);
foreach (var item in resultItems)
{
var newdy = Activator.CreateInstance(dyResult);
var properties = dyResult.GetProperties();
foreach (var property in properties)
{
var val = item[property.Name] ?? item[ToPascalCase(property.Name)];
ReflectionHelper.SetPropertyValue(newdy, property.Name, val);
}
list.Add(newdy);
}
result.Items = list;
return new PagedResultDto<dynamic>() { TotalCount = result.TotalCount, Items = result.Items };
}
private static string ToPascalCase(string camelCase)
{
if (string.IsNullOrEmpty(camelCase))
return camelCase;
return char.ToUpper(camelCase[0]) + camelCase.Substring(1);
}
public async Task<List<object>> ComplementAdditionalInfo(Guid id, List<dynamic> items)
{
var search = await _searchRepository.FindAsync(id);
if (search == null)
{
var recordType = await _recordTypeRepository.GetAsync(id);
search = ObjectMapper.Map<RecordTypeEntity, SearchEntity>(recordType);
}
var fieldDtos = await _GetFieldDtosAsync(search);
var searchResultDtos = await _GetSearchResultDto(fieldDtos, search);
ProvideAdditionalInfo(items, searchResultDtos, 0);
List<object> list = new List<object>();
// 1. 构建对象
var propertyTypes = GetPropertyTypes(searchResultDtos);
var dyResult = ReflectionHelper.CreateDynamicType("dyResult", propertyTypes);
foreach (var item in items)
{
var newdy = Activator.CreateInstance(dyResult);
var properties = dyResult.GetProperties();
foreach (var property in properties)
{
var val = item[property.Name];
ReflectionHelper.SetPropertyValue(newdy, property.Name, val);
}
list.Add(newdy);
}
return list;
}
public async Task<SearchDto> GetSearchResultsByCustomIdAsync(string customId)
{
//根据customId先取recordType
var entity = await _recordTypeRepository.GetAsync(p => p.CustomId == customId);
if (entity == null)
{
throw new UserFriendlyException(string.Format("未找到对应的RecodType"));
}
var result = await GetAsync(entity.Id);
return result;
}
#region 私有方法
protected async override Task DeleteBeforeCheckAsync(Guid id)
{
var entity = await _searchRepository.GetAsync(id);
if (entity.IsStandard) throw new BusinessException(MdsDomainErrorCodes.IsStandardDataNotCanDelete);
}
private async Task<AllResultDto<dynamic>> _fetchRemoteDataAsync(RecordTypeEntity recordType, FilterSearchResultRequestDto input, string methodName) // Search search,
{
var pageResult = new AllResultDto<dynamic>();
SetDefaultSorting(input, recordType);
string serviceModule = recordType.ServiceModule;
string recordTypeServiceName = recordType.ServiceName; //.EntityName;
int maxResultCount = input.MaxResultCount == 1 ? 1000 : input.MaxResultCount;
string strParams = string.Format("?Sorting={0}&SkipCount={1}&MaxResultCount={2}&IsInActive={3}&Filter={4}", input.Sorting, input.SkipCount, maxResultCount, input.IsInActive, input.Filter);
var result = await GetDaprInvokeResultAsync<PagedResultDto<dynamic>>(HttpMethod.Get, recordType.DaprAppId, serviceModule, recordTypeServiceName, methodName, strParams);
pageResult.TotalCount = result.TotalCount;
pageResult.Items = result.Items.ToList();
if (input.MaxResultCount == 1)
{
var pageCount = Math.Ceiling((double)pageResult.TotalCount / maxResultCount);
for (int i = 1; i < pageCount; i++)
{
int skipCount = 1000 * i;
string strParams1 = string.Format("?Sorting={0}&SkipCount={1}&MaxResultCount={2}&IsInActive={3}&Filter={4}", input.Sorting, skipCount, maxResultCount, input.IsInActive, input.Filter);
var result1 = await GetDaprInvokeResultAsync<PagedResultDto<dynamic>>(HttpMethod.Get, recordType.DaprAppId, serviceModule, recordType.ServiceName, methodName, strParams1); // .EntityName
pageResult.Items.AddRange(result1.Items);
}
}
return pageResult;
}
private static void SetDefaultSorting(FilterSearchResultRequestDto input, RecordTypeEntity recordType)
{
var hasInputSort = !string.IsNullOrWhiteSpace(input.Sorting) && recordType.RecordTypeFields.Any(f => f.FieldCustomId == input.Sorting.Split(" ")[0]);
if (hasInputSort) return;
if (recordType.IsList)
{
input.Sorting = "sort";
return;
}
var hasSort = recordType.RecordTypeFields.Any(f => f.FieldCustomId == "sort");
input.Sorting = hasSort ? "sort" : "id";
}
private async Task RepalceHistoryValueAsync(List<dynamic> items, Guid recordTypeId)
{
var recordType = await _recordTypeRepository.GetAsync(recordTypeId);
items.ForEach(item =>
{
string propertyName = Convert.ToString(item["propertyName"]);
var field = recordType.RecordTypeFields.Find(p => p.FieldCustomId.ToLower() == propertyName.ToLower());
if (field != null)
{
item["propertyName"] = field.Name;
}
});
}
private async Task ProvidefilterSourceListInfoAsync(List<dynamic> items, List<SearchResultDto> dicSearchResult)
{
List<Guid> filterUsingFieldIds = new List<Guid>();
items.ForEach(item =>
{
string filterUsing = Convert.ToString(item["filterUsingId"]);
var id = filterUsing.Split('.').LastOrDefault();
if (id != null) filterUsingFieldIds.Add(Guid.Parse(id));
});
var fieldDtos = await _recordTypeFieldAppService.GetListByIdsAsync(filterUsingFieldIds.Distinct().ToList());
var listOrRecordTypeFieldDtos = fieldDtos.Where(p => p.FieldViewType == FieldViewType._13_ListOrRecordType).ToList();
foreach (var item in items)
{
string filterUsing = Convert.ToString(item["filterUsingId"]);
var id = filterUsing.Split('.').LastOrDefault();
if (id == null) return;
var fieldDto = listOrRecordTypeFieldDtos.FirstOrDefault(p => p.Id.ToString() == id);
if (fieldDto == null)
{
item["value1_text"] = item["value1"];
item["value2_text"] = item["value2"];
}
else if (!string.IsNullOrWhiteSpace(Convert.ToString(item["value1"])))
{
string v1 = Convert.ToString(item["value1"]);
string v2 = Convert.ToString(item["value2"]);
var ids = new List<object> { v1, v2 };
var entities = await _GetEntitiesByIdsAsync(ids, fieldDto);
var entityV1 = entities.FirstOrDefault(p => p.id == v1 || p.value == v1);
if (entityV1 != null)
{
item["value1_text"] = GetFieldCustomIdText(entityV1, "[\"name\"]"); // "name"
}
var entityV2 = entities.FirstOrDefault(p => p.id == v2 || p.value == v2);
if (entityV2 != null)
{
item["value2_text"] = GetFieldCustomIdText(entityV2, "[\"name\"]");
}
}
}
}
private static string ReplaceMethodNamePlaceholders(string methodName, FilterSearchResultRequestDto input)
{
if (string.IsNullOrWhiteSpace(methodName)) return null;
Dictionary<string, string> placeholders = new Dictionary<string, string>();
if (!string.IsNullOrWhiteSpace(input.Filter) && input.Filter != "{}" && input.Filter != "[]")
{
var inputFilter = Newtonsoft.Json.Linq.JObject.Parse(input.Filter);
foreach (var property in inputFilter.Properties())
{
string propertyName = property.Name;
string propertyValue = property.Value.ToString();
placeholders[propertyName] = propertyValue;
}
}
// 使用正则表达式查找所有被大括号包围的占位符
var newMethodName = Regex.Replace(methodName, @"\{([^}]+)\}", match =>
{
// 获取大括号内的内容(占位符)
string placeholder = match.Groups[1].Value;
// 尝试从字典中获取替换值
// 如果字典中存在该占位符,则返回替换值
// 如果不存在,则返回原始匹配(即保留大括号和占位符内容)
if (placeholders.ContainsKey(placeholder))
{
var val = placeholders[placeholder];
placeholders.Remove(placeholder);
return val;
}
return match.Value;
});
// 检查替换后的字符串中是否还有剩余的占位符
var matches = Regex.Matches(newMethodName, @"\{([^}]+)\}");
var remainingPlaceholders = matches.Cast<Match>().Select(m => m.Groups[1].Value).ToList();
if (remainingPlaceholders.Any()) throw new UserFriendlyException(string.Format("方法{0}中,缺少参数{1}", methodName, string.Join(",", remainingPlaceholders)));
input.Filter = Newtonsoft.Json.JsonConvert.SerializeObject(placeholders);
return newMethodName;
}
private async Task<string> _GetFilterAsync(FilterSearchResultRequestDto input, SearchEntity search, RecordTypeEntity recordType, List<SearchResultDto> searchResultDtos)
{
List<FilterModel> filters = new List<FilterModel>();
if (!string.IsNullOrWhiteSpace(input.Filter) && input.Filter != "{}" && input.Filter != "[]")
{
var inputFilter = Newtonsoft.Json.Linq.JObject.Parse(input.Filter);
// 遍历对象的所有属性
// 1. 添加动态数据过滤
// 1.1 当属性里有Filter_RecordTypeFieldId(特定字段,根据id查找RecordTypeFieldFilterSourceListDto 列表)构建过滤条件;
// 1.2 comparedField 使用参数传过来的值,替换RecordTypeFieldFilterSourceListDto中CompareField的值;
// 1.3 构建过滤条件,并合并其他用户动态传递过来的参数
var hasFilterField = inputFilter.Properties().Any(p => p.Name == "filter_RecordTypeFieldId");
if (hasFilterField)
{
var recordTypeFieldId = inputFilter["filter_RecordTypeFieldId"].ToString();
var filterSourceList = await _recordFieldFilterSourceListRepository.GetListAsync(p => p.RecordTypeFieldId == Guid.Parse(recordTypeFieldId));
var filterSourceListDtos = ObjectMapper.Map<List<RecordTypeFieldFilterSourceListEntity>, List<RecordTypeFieldFilterSourceListDto>>(filterSourceList);
filterSourceListDtos = filterSourceListDtos.OrderBy(p => p.Line).ToList();
filterSourceListDtos.ForEach(line =>
{
if (line.CompareToField.HasValue)
{
var compareValue = inputFilter["filter_" + line.FilterUsing].ToString();
line.Value1 = compareValue.StartsWith("opt_") ? compareValue.Substring(compareValue.Split(" ")[0].Length + 1) : compareValue;
if (line.Value1 == "undefined" || line.Value1 == "null") line.Value1 = Guid.Empty.ToString();
inputFilter.Remove("filter_" + line.FilterUsing);
}
});
var filterList1 = ObjectMapper.Map<List<RecordTypeFieldFilterSourceListDto>, List<FilterModel>>(filterSourceListDtos);
filterList1[filterList1.Count - 1].LogicalOperator = LogicalOperator.And;
filters = filterList1;
inputFilter.Remove("filter_RecordTypeFieldId");
}
foreach (var property in inputFilter.Properties())
{
string propertyName = property.Name;
// object propertyValue = property.Value;
string propertyValue = property.Value.ToString();
if (string.IsNullOrWhiteSpace(propertyValue)) continue;
int optType = propertyValue.StartsWith("opt_") ? Convert.ToInt32(propertyValue.Substring(4, propertyValue.Split(" ")[0].Length - 4)) : (int)OperatorType.Equal;
propertyValue = propertyValue.StartsWith("opt_") ? propertyValue.Substring(propertyValue.Split(" ")[0].Length + 1) : propertyValue;
string propertyValue2 = string.Empty;
OperatorType operatorType = (OperatorType)optType;
if (operatorType == OperatorType.Between)
{
var values = JsonSerializer.Deserialize<List<string>>(propertyValue);
propertyValue = values[0];
propertyValue2 = values[1];
if (!string.IsNullOrWhiteSpace(propertyValue) && !string.IsNullOrWhiteSpace(propertyValue2))
{
FilterModel filter1 = new FilterModel();
filter1.Not = false;
filter1.OpenParens = 1;
filter1.FilterUsing = propertyName;
filter1.OperatorType = OperatorType.GreaterThanOrEqual;
filter1.Value1 = propertyValue.ToString();
filter1.Value2 = string.Empty;
filter1.CloseParens = 0;
filter1.LogicalOperator = LogicalOperator.And;
filter1.Line = -1;
filters.Add(filter1);
FilterModel filter2 = new FilterModel();
filter2.Not = false;
filter2.OpenParens = 1;
filter2.FilterUsing = propertyName;
filter2.OperatorType = OperatorType.LessThanOrEqual;
filter2.Value1 = propertyValue2.ToString();
filter2.Value2 = string.Empty;
filter2.CloseParens = 0;
filter2.LogicalOperator = LogicalOperator.And;
filter2.Line = -1;
filters.Add(filter2);
}
else if (string.IsNullOrWhiteSpace(propertyValue) && !string.IsNullOrWhiteSpace(propertyValue2))
{
FilterModel filter2 = new FilterModel();
filter2.Not = false;
filter2.OpenParens = 0;
filter2.FilterUsing = propertyName;
filter2.OperatorType = OperatorType.LessThanOrEqual;
filter2.Value1 = propertyValue2.ToString();
filter2.Value2 = string.Empty;
filter2.CloseParens = 0;
filter2.LogicalOperator = LogicalOperator.And;
filter2.Line = -1;
filters.Add(filter2);
}
else if (!string.IsNullOrWhiteSpace(propertyValue) && string.IsNullOrWhiteSpace(propertyValue2))
{
FilterModel filter1 = new FilterModel();
filter1.Not = false;
filter1.OpenParens = 0;
filter1.FilterUsing = propertyName;
filter1.OperatorType = OperatorType.GreaterThanOrEqual;
filter1.Value1 = propertyValue.ToString();
filter1.Value2 = string.Empty;
filter1.CloseParens = 0;
filter1.LogicalOperator = LogicalOperator.And;
filter1.Line = -1;
filters.Add(filter1);
}
}
else if (propertyName.ToLower() == "keywords")
{
if (string.IsNullOrWhiteSpace(propertyValue) || propertyValue == "null") continue;
var kvFilters = GetKeyWordsFilterModels(propertyValue, searchResultDtos);
filters.AddRange(kvFilters);
}
else
{
FilterModel filter = new FilterModel();
filter.Not = false;
filter.OpenParens = 0;
filter.FilterUsing = propertyName;
filter.OperatorType = (OperatorType)optType; // OperatorType.Equal;
filter.Value1 = propertyValue.ToString();
filter.Value2 = propertyValue2;
filter.LogicalOperator = LogicalOperator.And;
filter.CloseParens = 0;
filter.Line = -1;
filters.Add(filter);
}
}
}
if (recordType.IsList)
{
FilterModel filter = new FilterModel();
filter.Not = false;
filter.OpenParens = 0;
filter.FilterUsing = "RecordTypeId";
filter.OperatorType = OperatorType.Equal;
filter.Value1 = recordType.Id.ToString();
filter.Value2 = string.Empty;
filter.LogicalOperator = LogicalOperator.And;
filter.CloseParens = 0;
filter.Line = -1;
filters.Add(filter);
}
if (search.SearchCriterias != null && search.SearchCriterias.Count > 0)
{
// 子查询处理
foreach (var item in search.SearchCriterias)
{
FilterModel filterModel = new FilterModel();
filterModel.Not = item.Not;
filterModel.OpenParens = item.OpenParens;
filterModel.FilterUsing = item.Filter;
filterModel.OperatorType = item.OperatorType;
filterModel.Value1 = item.Value1;
filterModel.Value2 = item.Value2;
filterModel.LogicalOperator = item.LogicalOperator;
filterModel.CloseParens = item.CloseParens;
filterModel.Line = item.Line;
filters.Add(filterModel);
}
await _ResetSubScopeFilterAsync(recordType, filters);
}
for (int i = 0; i < filters.Count; i++)
{
filters[i].Line = i;
}
var strFilter = filters.Count > 0 ? JsonSerializer.Serialize(filters) : string.Empty;
return strFilter;
}
public async Task ProvideAdditionalInfo(List<dynamic> items, List<SearchResultDto> dicSearchResult, int level)
{
if (level > 5 || items.Count == 0) return;
List<string> containCustomIdTexts = new List<string>();
var textSearchResult = dicSearchResult.Where(p => !string.IsNullOrWhiteSpace(p.FieldCustomId) && p.FieldCustomId.Contains("_text")).ToList();
if (textSearchResult.Count > 0)
{
containCustomIdTexts = textSearchResult.Select(p => p.FieldCustomId).ToList();
}
var searchResultDtos = dicSearchResult.Where(p => (p.field.FieldViewType == FieldViewType._13_ListOrRecordType || p.field.FieldViewType == FieldViewType._23_Dynamic) && !containCustomIdTexts.Contains(p.FieldCustomId + "_text")).ToList();
if (searchResultDtos.Count == 0) return;
foreach (var searchResultDto in searchResultDtos)
{
var fieldDto = searchResultDto.field;
if (fieldDto.FieldViewType == FieldViewType._23_Dynamic) // 动态字段类型,其text文本,由服务传递,不在这里聚合
{
bool flag = dicSearchResult.Any(p => p.FieldCustomId == searchResultDto.FieldCustomId + "_text");
if (!flag)
{
var searchResultDtoText = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchResultDto>(Newtonsoft.Json.JsonConvert.SerializeObject(searchResultDto));
searchResultDtoText!.FieldCustomId = searchResultDto.FieldCustomId + "_text";
searchResultDtoText.field.FieldViewType = FieldViewType._7_FreeFormText;
dicSearchResult.Add(searchResultDtoText);
}
continue;
}
if (fieldDto.FieldViewType != FieldViewType._13_ListOrRecordType) continue;
//if (fieldDto.CustomId.ToLower() == "filterUsing".ToLower())
//{
// foreach (var item in items)
// {
// item[searchResultDto.FieldCustomId + "_text"] = GetFieldCustomIdText(item, searchResultDto.FieldCustomId); // item[searchResultDto.FieldCustomId];
// bool flag = dicSearchResult.Any(p => p.FieldCustomId == searchResultDto.FieldCustomId + "_text");
// if (!flag)
// {
// var searchResultDtoText = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchResultDto>(Newtonsoft.Json.JsonConvert.SerializeObject(searchResultDto));
// searchResultDtoText.FieldCustomId = searchResultDto.FieldCustomId + "_text";
// searchResultDtoText.field.FieldViewType = FieldViewType._7_FreeFormText;
// dicSearchResult.Add(searchResultDtoText);
// }
// }
// continue;
//}
var ids = items.Select(p => p[searchResultDto.FieldCustomId]).Distinct().ToList();
ids.RemoveAll(p => p == null);
if (ids.Count == 0)
{
continue;
}
var groupedLists = ids
.Select((value, index) => new { Index = index, Value = value })
.GroupBy(x => x.Index / 10)
.Select(g => g.Select(x => x.Value).ToList())
.ToList();
List<dynamic> resultItemlist = new List<dynamic>();
#region 并行
Task<List<dynamic>>[] taskArray = new Task<List<dynamic>>[groupedLists.Count];
for (var i = 0; i < groupedLists.Count; i++)
{
var groupIds = groupedLists[i];
taskArray[i] = _GetEntitiesByIdsAsync(groupIds, fieldDto);
}
// 等待所有任务完成
Task.WaitAll(taskArray);
foreach (var task in taskArray)
{
var resultItems = task.Result;
if (resultItems != null) resultItemlist.AddRange(resultItems);
}
#endregion
foreach (var item in items)
{
string itemid = item[searchResultDto.FieldCustomId];
if (string.IsNullOrWhiteSpace(itemid)) continue;
var resultItem = fieldDto.FieldListOrRecordTypeIsList ? resultItemlist.FirstOrDefault(p => p.value == itemid && p.recordTypeId == fieldDto.FieldListOrRecordTypeId) : resultItemlist.FirstOrDefault(p => string.Equals(Convert.ToString(p.id), itemid, StringComparison.OrdinalIgnoreCase));
if (string.IsNullOrWhiteSpace(item[searchResultDto.FieldCustomId + "_text"] as string))
{
item[searchResultDto.FieldCustomId + "_text"] = resultItem == null ? "" : GetFieldCustomIdText(resultItem, searchResultDto.field.LabelFields); // resultItem.name;
}
//item[searchResultDto.FieldCustomId + "_text"] = resultItem == null ? "" : GetFieldCustomIdText(resultItem, searchResultDto.field.LabelFields); // resultItem.name;
bool flag = dicSearchResult.Any(p => p.FieldCustomId == searchResultDto.FieldCustomId + "_text");
if (!flag)
{
var searchResultDtoText = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchResultDto>(Newtonsoft.Json.JsonConvert.SerializeObject(searchResultDto));
searchResultDtoText.FieldCustomId = searchResultDto.FieldCustomId + "_text";
searchResultDtoText.field.FieldViewType = FieldViewType._7_FreeFormText;
dicSearchResult.Add(searchResultDtoText);
}
var searchResults = dicSearchResult.FindAll(p => p.FieldId == fieldDto.Id && p.LinkFieldId != null && p.LinkFieldId != Guid.Empty);
foreach (var searchResult in searchResults)
{
var linkField = searchResult.field;
item[searchResult.FieldCustomId] = resultItem[linkField.CustomId];
}
}
}
level++;
ProvideAdditionalInfo(items, dicSearchResult, level);
}
private static string GetFieldCustomIdText(dynamic item, string? fieldName)
{
if (!string.IsNullOrEmpty(fieldName))
{
var array = JArray.Parse(fieldName);
fieldName = array[0].ToString();
}
else
{
fieldName = "name";
}
if (item is JToken jToken)
{
JObject? jObject = jToken as JObject;
if (jObject == null)
{
return string.Empty;
}
foreach (var property in jObject)
{
if (
(property.Key== fieldName) && property.Value != null && property.Value.Type != JTokenType.Null)
{
return property.Value.ToString();
}
}
}
return string.Empty;
}
private static List<FilterModel> GetKeyWordsFilterModels(string propertyValue, List<SearchResultDto> searchResultDtos)
{
List<FilterModel> filters = new List<FilterModel>();
List<string> keywordFields = new List<string>() { "name", "no", "code", "customId" };
List<string> keywordSearchResultDtos = searchResultDtos.Where(p => p.FieldCustomId.ToLower().EndsWith("name") || p.FieldCustomId.ToLower().EndsWith("no") || p.FieldCustomId.ToLower().EndsWith("code")).Select(p => p.FieldCustomId).ToList();
keywordFields = new HashSet<string>(keywordFields.Concat(keywordSearchResultDtos), StringComparer.OrdinalIgnoreCase).ToList();
for (int i = 0; i < keywordFields.Count; i++)
{
var item = keywordFields[i];
FilterModel filter = new FilterModel();
filter.Not = false;
filter.OpenParens = 0;
filter.FilterUsing = item;
filter.OperatorType = OperatorType.Contains;
filter.Value1 = propertyValue;
filter.Value2 = string.Empty;
filter.CloseParens = 0;
filter.LogicalOperator = LogicalOperator.Or;
filter.Line = -1;
if (i == 0) filter.OpenParens = 1;
if (i == keywordFields.Count - 1)
{
filter.LogicalOperator = LogicalOperator.And;
filter.CloseParens = 1;
}
filters.Add(filter);
}
return filters;
}
private async Task<List<SearchResultDto>> _GetSearchResultDto(List<RecordTypeFieldDto> fieldDtos, SearchEntity search)
{
var recordType = await _recordTypeRepository.GetAsync(search.RecordTypeId);
List<SearchResultDto> dicSearchResult = new List<SearchResultDto>();
foreach (var searchResult in search.SearchResults)
{
var searchResultDto = ObjectMapper.Map<SearchResultEntity, SearchResultDto>(searchResult);
var fieldDto = fieldDtos.Find(p => p.Id == searchResult.FieldId);
searchResultDto.FieldCustomId = fieldDto.CustomId;
searchResultDto.field = fieldDto;
if (fieldDto.FieldViewType != FieldViewType._13_ListOrRecordType)
{
dicSearchResult.Add(searchResultDto);
continue;
}
if (searchResult.LinkFieldId == null)
{
var newFieldDto = await _UpdateFieldDtoAsync(recordType, fieldDto);
searchResultDto.FieldCustomId = newFieldDto.CustomId;
searchResultDto.field = newFieldDto;
dicSearchResult.Add(searchResultDto);
}
else
{
var linkFieldDto = fieldDtos.Find(p => p.Id == searchResult.LinkFieldId);
var newRecordType = await _recordTypeRepository.GetAsync(searchResultDto.field.FieldListOrRecordTypeId.Value);
var newFieldDto = await _UpdateFieldDtoAsync(newRecordType, linkFieldDto);
searchResultDto.FieldCustomId = string.Format("{0}.{1}", fieldDto.CustomId, newFieldDto.CustomId);
searchResultDto.field = newFieldDto;
dicSearchResult.Add(searchResultDto);
var linkFieldSearchResultDto = dicSearchResult.Any(p => p.FieldId == searchResult.FieldId && (p.LinkFieldId == null || p.LinkFieldId == Guid.Empty));
var linkFieldSearchResult = search.SearchResults.Any(p => p.FieldId.Equals(searchResult.FieldId) && (p.LinkFieldId == null || p.LinkFieldId == Guid.Empty));
if (!linkFieldSearchResultDto && !linkFieldSearchResult)
{
var linkFieldSearchResultDto1 = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchResultDto>(Newtonsoft.Json.JsonConvert.SerializeObject(searchResultDto));
var fieldDto1 = fieldDtos.Find(p => p.Id == linkFieldSearchResultDto1.FieldId);
var newFieldDto1 = await _UpdateFieldDtoAsync(recordType, fieldDto1);
linkFieldSearchResultDto1.FieldCustomId = newFieldDto1.CustomId;
linkFieldSearchResultDto1.field = newFieldDto1;
linkFieldSearchResultDto1.LinkFieldId = null;
dicSearchResult.Add(linkFieldSearchResultDto1);
}
}
}
return dicSearchResult;
}
private async Task<List<SearchAvailableFilterDto>> _GetSearchAvailableFilterDtos(List<RecordTypeFieldDto> fieldDtos, SearchEntity search)
{
var recordType = await _recordTypeRepository.GetAsync(search.RecordTypeId);
List<SearchAvailableFilterDto> dicSearchResult = new List<SearchAvailableFilterDto>(); // Dictionary<string, FieldDto>();
foreach (var searchAvailableFilter in search.SearchAvailableFilters)
{
var searchResultDto = ObjectMapper.Map<SearchAvailableFilterEntity, SearchAvailableFilterDto>(searchAvailableFilter);
var fieldDto = fieldDtos.Find(p => p.Id == searchAvailableFilter.FieldId);
if (fieldDto == null) continue;
searchResultDto.FieldCustomId = fieldDto.CustomId;
searchResultDto.Field = fieldDto;
if (fieldDto.FieldViewType != FieldViewType._13_ListOrRecordType)
{
dicSearchResult.Add(searchResultDto);
continue;
}
if (searchAvailableFilter.LinkFieldId == null)
{
var newFieldDto = await _UpdateFieldDtoAsync(recordType, fieldDto);
searchResultDto.FieldCustomId = newFieldDto.CustomId;
searchResultDto.Field = newFieldDto;
dicSearchResult.Add(searchResultDto);
}
else
{
var linkFieldDto = fieldDtos.Find(p => p.Id == searchAvailableFilter.LinkFieldId);
var newRecordType = await _recordTypeRepository.GetAsync(searchResultDto.Field.FieldListOrRecordTypeId.Value);
var newFieldDto = await _UpdateFieldDtoAsync(newRecordType, linkFieldDto);
searchResultDto.FieldCustomId = string.Format("{0}.{1}", fieldDto.CustomId, newFieldDto.CustomId);
searchResultDto.Field = newFieldDto;
dicSearchResult.Add(searchResultDto);
var linkFieldSearchResultDto = dicSearchResult.Any(p => p.FieldId == searchAvailableFilter.FieldId && (p.LinkFieldId == null || p.LinkFieldId == Guid.Empty));
var linkFieldSearchResult = search.SearchResults.Any(p => p.FieldId.Equals(searchAvailableFilter.FieldId) && (p.LinkFieldId == null || p.LinkFieldId == Guid.Empty));
if (!linkFieldSearchResultDto && !linkFieldSearchResult)
{
var linkFieldSearchResultDto1 = Newtonsoft.Json.JsonConvert.DeserializeObject<SearchAvailableFilterDto>(Newtonsoft.Json.JsonConvert.SerializeObject(searchResultDto));
var fieldDto1 = fieldDtos.Find(p => p.Id == linkFieldSearchResultDto1.FieldId);
var newFieldDto1 = await _UpdateFieldDtoAsync(recordType, fieldDto1);
linkFieldSearchResultDto1.FieldCustomId = newFieldDto1.CustomId;
linkFieldSearchResultDto1.Field = newFieldDto1;
linkFieldSearchResultDto1.LinkFieldId = null;
dicSearchResult.Add(linkFieldSearchResultDto1);
}
}
}
return dicSearchResult;
}
private async Task<RecordTypeFieldDto> _UpdateFieldDtoAsync(RecordTypeEntity recordType, RecordTypeFieldDto fieldDto)
{
var copyFieldDto = Newtonsoft.Json.JsonConvert.DeserializeObject<RecordTypeFieldDto>(Newtonsoft.Json.JsonConvert.SerializeObject(fieldDto));
if (copyFieldDto.FieldViewType != FieldViewType._13_ListOrRecordType) return copyFieldDto;
var recordField = recordType.RecordTypeFields.Find(p => p.FieldId == fieldDto.Id);
if (recordField != null && recordField.FieldListOrRecordTypeId.HasValue)
{
var fieldRecordType = await _recordTypeRepository.GetAsync(recordField.FieldListOrRecordTypeId.Value, false);
copyFieldDto.RecordTypeId = recordField.FieldListOrRecordTypeId.Value;
copyFieldDto.FieldListOrRecordTypeCustomId = fieldRecordType.CustomId;
copyFieldDto.FieldListOrRecordTypeServiceName = fieldRecordType.ServiceName;
copyFieldDto.FieldListOrRecordTypeEntityName = fieldRecordType.EntityName;
copyFieldDto.FieldListOrRecordTypeIsList = fieldRecordType.IsList;
copyFieldDto.FieldListOrRecordTypeName = fieldRecordType.Name;
copyFieldDto.FieldListOrRecordTypeServiceModule = fieldRecordType.ServiceModule;
}
return copyFieldDto;
}
private async Task<List<dynamic>> _GetEntitiesByIdsAsync(List<object> ids, RecordTypeFieldDto fieldDto)
{
if (fieldDto.FieldViewType != FieldViewType._13_ListOrRecordType) return null;
List<FilterModel> filters = new List<FilterModel>();
int line = 1;
foreach (var id in ids)
{
if (fieldDto.FieldListOrRecordTypeIsList)
{
FilterModel filter = new FilterModel();
filter.Not = false;
filter.OpenParens = 1;
filter.FilterUsing = fieldDto.FieldListOrRecordTypeIsList ? "value" : "Id";
filter.OperatorType = OperatorType.Equal;
filter.Value1 = id.ToString();
filter.Value2 = string.Empty;
filter.LogicalOperator = LogicalOperator.And;
filter.CloseParens = 0;
filter.Line = line;
filters.Add(filter);
FilterModel filter1 = new FilterModel();
filter1.Not = false;
filter1.OpenParens = 0;
filter1.FilterUsing = "RecordTypeId";
filter1.OperatorType = OperatorType.Equal;
filter1.Value1 = fieldDto.FieldListOrRecordTypeId.ToString();
filter1.Value2 = string.Empty;
filter1.LogicalOperator = LogicalOperator.Or;
filter1.CloseParens = 1;
filter1.Line = line + 1;
filters.Add(filter1);
line = line + 2;
}
else
{
FilterModel filter = new FilterModel();
filter.Not = false;
filter.OpenParens = 0;
filter.FilterUsing = fieldDto.OptionValue; // fieldDto.FieldListOrRecordTypeIsList ? "value" : "Id";
filter.OperatorType = OperatorType.Equal;
filter.Value1 = id.ToString();
filter.Value2 = string.Empty;
filter.LogicalOperator = LogicalOperator.Or;
filter.CloseParens = 0;
filter.Line = line;
filters.Add(filter);
line = line + 1;
}
}
var strFilter = filters.Count > 0 ? JsonSerializer.Serialize(filters) : string.Empty;
//string recordTypeEntityName = fieldDto.FieldListOrRecordTypeEntityName;
string recordTypeServiceName = fieldDto.FieldListOrRecordTypeServiceName ?? string.Empty;
string strParams = string.Format("?SkipCount={0}&MaxResultCount=1000&Filter={1}", 0, strFilter);
string methodName = fieldDto.FieldListOrRecordTypeMethodName ?? string.Empty;
var result = await GetDaprInvokeResultAsync<PagedResultDto<dynamic>>(HttpMethod.Get, fieldDto.FieldListOrRecordTypeDaprAppId, fieldDto.FieldListOrRecordTypeServiceModule, recordTypeServiceName, methodName, strParams); // Todo: 暂不支持自定义MethodName的recordType
return (List<dynamic>)result.Items;
}
private async Task<List<RecordTypeFieldDto>> _GetFieldDtosAsync(SearchEntity search)
{
var originFieldIds = search.SearchResults.Select(p => p.FieldId).Distinct().ToList();
var linkFieldIds = search.SearchResults.Where(p => p.LinkFieldId.HasValue).Select(p => p.LinkFieldId.Value).ToList();
var availableFilter = search.SearchAvailableFilters.Select(p => p.FieldId).Distinct().ToList();
var avaiLinkFieldIds = search.SearchAvailableFilters.Where(p => p.LinkFieldId.HasValue).Select(p => p.LinkFieldId.Value).ToList();
var filterFieldIds = search.SearchCriterias.Where(p => !string.IsNullOrEmpty(p.Filter)).Select(p => p.Filter).ToList();
List<Guid> fieldIds = new List<Guid>();
fieldIds.AddRange(originFieldIds);
fieldIds.AddRange(linkFieldIds);
fieldIds.AddRange(availableFilter);
fieldIds.AddRange(avaiLinkFieldIds);
foreach (var item in filterFieldIds)
{
Guid filter = new Guid() ;
if (Guid.TryParse(item,out filter))
{
fieldIds.Add(filter);
}
}
fieldIds = fieldIds.Distinct().ToList();
var dtos = await _recordTypeFieldAppService.GetListByIdsAsync(fieldIds);
return dtos;
}
private Dictionary<string, Type> GetPropertyTypes(List<SearchResultDto> searchResultDtos)
{
Dictionary<string, Type> propertyTypes = new Dictionary<string, Type>();
foreach (var searchResultDto in searchResultDtos)
{
if (propertyTypes.ContainsKey(searchResultDto.FieldCustomId)) continue;
if (searchResultDto.field.FieldViewType == FieldViewType._13_ListOrRecordType)
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(string));
}
else if (searchResultDto.field.FieldViewType == FieldViewType._12_IntegerNumber)
{
if (searchResultDto.field.Mandatory)
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(int));
}
else
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(int?));
}
}
else if (searchResultDto.field.FieldViewType == FieldViewType._1_Currency
|| searchResultDto.field.FieldViewType == FieldViewType._4_DecimalNumber
|| searchResultDto.field.FieldViewType == FieldViewType._16_Percent)
{
if(searchResultDto.field.Mandatory)
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(decimal));
}
else
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(decimal?));
}
}
else if (searchResultDto.field.FieldViewType == FieldViewType._0_CheckBox)
{
if(searchResultDto.field.Mandatory)
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(bool));
}
else
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(bool?));
}
}
else
{
propertyTypes.Add(searchResultDto.FieldCustomId, typeof(string));
}
}
return propertyTypes;
}
protected override void MapToEntity(CreateOrUpdateSearchDto updateInput, SearchEntity entity)
{
base.MapToEntity(updateInput, entity);
//固定条件映射
var cearchCriteriaIds = updateInput.SearchCriterias.Select(p => p.Id).ToList();
entity.SearchCriterias.RemoveAll(u => !cearchCriteriaIds.Contains(u.Id));
foreach (var item in updateInput.SearchCriterias)
{
var oldEntity = entity.SearchCriterias.Find(p => p.Id == item.Id);
if (oldEntity == null)
{
entity.SearchCriterias.Add(ObjectMapper.Map<CreateOrUpdateSearchCriteriaDto, SearchCriteriaEntity>(item));
}
else
{
ObjectMapper.Map(item, oldEntity);
}
}
//可选条件映射
var searchAvailableFiltersIds = updateInput.SearchAvailableFilters.Select(p => p.Id).ToList();
entity.SearchAvailableFilters.RemoveAll(u => !searchAvailableFiltersIds.Contains(u.Id));
foreach (var item in updateInput.SearchAvailableFilters)
{
var oldEntity = entity.SearchAvailableFilters.Find(p => p.Id == item.Id);
if (oldEntity == null)
{
entity.SearchAvailableFilters.Add(ObjectMapper.Map<CreateOrUpdateSearchAvailableFilterDto, SearchAvailableFilterEntity>(item));
}
else
{
ObjectMapper.Map(item, oldEntity);
}
}
//结果集映射
var searchResultIds = updateInput.SearchResults.Select(p => p.Id).ToList();
entity.SearchResults.RemoveAll(u => !searchResultIds.Contains(u.Id));
foreach (var item in updateInput.SearchResults)
{
var oldEntity = entity.SearchResults.Find(p => p.Id == item.Id);
if (oldEntity == null)
{
entity.SearchResults.Add(ObjectMapper.Map<CreateOrUpdateSearchResultDto, SearchResultEntity>(item));
}
else
{
ObjectMapper.Map(item, oldEntity);
}
}
//SetIdForGuids(entity);
}
protected override void SetIdForGuids(SearchEntity entity)
{
base.SetIdForGuids(entity);
foreach (var item in entity.SearchAvailableFilters)
{
if (item.Id == Guid.Empty) EntityHelper.TrySetId(item, () => GuidGenerator.Create(), true);
}
foreach (var item in entity.SearchCriterias)
{
if (item.Id == Guid.Empty) EntityHelper.TrySetId(item, () => GuidGenerator.Create(), true);
}
foreach (var item in entity.SearchResults)
{
if (item.Id == Guid.Empty) EntityHelper.TrySetId(item, () => GuidGenerator.Create(), true);
}
}
// 处理子(join表)查询
private async Task _ResetSubScopeFilterAsync(RecordTypeEntity recordType, List<FilterModel> filters)
{
var tasks = new List<Task>();
foreach (var filter in filters)
{
//var currFilter = filters[i];
var filterUsings = filter.FilterUsing.Split(".");
if (filterUsings.Count() > 5) throw new UserFriendlyException("最多只能5级关联查询");
if (filterUsings.Count() == 1) continue;
tasks.Add(_ResetSubScopeFilterAsync1(recordType.Id, filter));
}
await Task.WhenAll(tasks);
}
private async Task _ResetSubScopeFilterAsync1(Guid recordTypeId, FilterModel currFilter)
{
var filterUsings = currFilter.FilterUsing.Split(".");
Guid currRecordTypeId = recordTypeId;
Stack<RecordTypeFieldDto> recordTypeFieldDtoStack = new Stack<RecordTypeFieldDto>();
for (int j = 0; j < filterUsings.Count(); j++)
{
var filter = filterUsings[j];
var recordTypeFieldDto = await _recordTypeFieldAppService.GetByCustomIdAsync(currRecordTypeId, filter);
currRecordTypeId = recordTypeFieldDto.FieldListOrRecordTypeId.Value;
recordTypeFieldDtoStack.Push(recordTypeFieldDto);
}
FilterSearchResultRequestDto filterSearchResultRequestDto = new FilterSearchResultRequestDto() { MaxResultCount = 1, SkipCount = 0, Sorting = "sort", Filter = "" };
var subFilter = Newtonsoft.Json.JsonConvert.DeserializeObject<FilterModel>(Newtonsoft.Json.JsonConvert.SerializeObject(currFilter));
var recordTypeFieldDtoS = recordTypeFieldDtoStack.Pop();
subFilter.FilterUsing = recordTypeFieldDtoS.CustomId;
List<FilterModel> filterModels = new List<FilterModel>() { subFilter };
var strFilter = filterModels.Count > 0 ? JsonSerializer.Serialize(filterModels) : string.Empty;
for (int j = 1; j < filterUsings.Count(); j++)
{
var recordType1 = await _recordTypeRepository.GetAsync(recordTypeFieldDtoS.RecordTypeId);
// 查询远程数据列表
filterSearchResultRequestDto.Filter = strFilter;
//string methodName = string.Format("api/{0}/{1}/{2}", recordType1.ServiceModule, recordType1.EntityName, strParams);
var result = await _fetchRemoteDataAsync(recordType1, filterSearchResultRequestDto, null); // Todo: 暂不支持自定义MethodName的recordtype 作为子记录
List<Guid> ids = new List<Guid>();
foreach (var item in result.Items)
{
ids.Add(item.id);
}
recordTypeFieldDtoS = recordTypeFieldDtoStack.Pop();
subFilter.FilterUsing = recordTypeFieldDtoS.CustomId;
subFilter.OperatorType = OperatorType.AnyOf;
subFilter.Value1 = Newtonsoft.Json.JsonConvert.SerializeObject(ids);
}
currFilter.FilterUsing = recordTypeFieldDtoS.CustomId;
currFilter.OperatorType = OperatorType.AnyOf;
currFilter.Value1 = subFilter.Value1;
}
#endregion
/// <summary>
/// 根据recordTypeId查询视图列表,及明细
/// </summary>
/// <param name="recordTypeId"></param>
/// <returns></returns>
public async Task<List<SearchDto>> GetListDetailsAsync(Guid recordTypeId)
{
List<SearchDto> result = [];
var list = await _searchRepository.GetListAsync(o => o.RecordTypeId == recordTypeId);
if (list.Any())
{
var searchIds = list.Select(o => o.Id).ToList();
var searchAvailableFilters = await _searchAvailableFilterRepository.GetListAsync(o => searchIds.Contains(o.SearchId));
var searchResults = await _searchResultRepository.GetListAsync(o => searchIds.Contains(o.SearchId));
var searchCriterias = await _searchCriteriaRepository.GetListAsync(o => searchIds.Contains(o.SearchId));
//需要查询字段集合
var havingSelfileIds = new List<Guid>();
havingSelfileIds.AddRange(searchAvailableFilters.Select(o => o.FieldId).Distinct().ToList());
havingSelfileIds.AddRange(searchResults.Select(o => o.FieldId).Distinct().ToList());
havingSelfileIds.AddRange(searchAvailableFilters.Where(o => o.LinkFieldId.HasValue).Select(o => o.LinkFieldId.Value).Distinct().ToList());
havingSelfileIds = havingSelfileIds.Distinct().ToList();
var fieldDtos = await _recordTypeFieldAppService.GetListByIdsAsync(havingSelfileIds);
foreach (var item in list)
{
item.SearchResults = searchResults.Where(o => o.SearchId == item.Id).OrderBy(o => o.Sort).ToList();
item.SearchAvailableFilters = searchAvailableFilters.Where(o => o.SearchId == item.Id).OrderBy(o => o.Sort).ToList();
item.SearchCriterias = searchCriterias.Where(o => o.SearchId == item.Id).OrderBy(o => o.Sort).ToList();
}
result = ObjectMapper.Map<List<SearchEntity>, List<SearchDto>>(list);
foreach (var item in result)
{
//可选条件字段信息赋值
if (item.SearchAvailableFilters.Any())
{
foreach (var itemAvailableFilters in item.SearchAvailableFilters)
{
var fieldInfo = fieldDtos.FirstOrDefault(o => o.Id == itemAvailableFilters.FieldId);
if (fieldInfo != null)
{
itemAvailableFilters.Field = fieldInfo;
itemAvailableFilters.FieldCustomId = fieldInfo.FieldCustomId;
}
}
}
//结果集字段信息赋值
if (item.SearchResults.Any())
{
foreach (var itemSearchResults in item.SearchResults)
{
var fieldInfo = fieldDtos.FirstOrDefault(o => o.Id == itemSearchResults.FieldId);
if (fieldInfo != null)
{
itemSearchResults.field = fieldInfo;
itemSearchResults.FieldCustomId = fieldInfo.FieldCustomId;
itemSearchResults.FieldName = fieldInfo.Name;
}
}
}
}
}
return result;
}
}
// 转换小驼峰方法
public static class CamelCaseHelper
{
// 主入口:List<dynamic> → List<dynamic>
public static List<dynamic> ToCamelCaseList(List<dynamic> list)
{
var jArray = JArray.FromObject(list); // 转 JArray
var camelJArray = (JArray)ToCamelCase(jArray); // 转 key
return camelJArray.ToObject<List<dynamic>>(); // 转回 List<dynamic>
}
// 递归转换 JToken
private static JToken ToCamelCase(JToken token)
{
if (token is JObject obj)
{
var newObj = new JObject();
foreach (var property in obj.Properties())
{
string camelName = ToCamelCase(property.Name);
newObj[camelName] = ToCamelCase(property.Value);
}
return newObj;
}
else if (token is JArray array)
{
var newArray = new JArray();
foreach (var item in array)
{
newArray.Add(ToCamelCase(item));
}
return newArray;
}
else
{
return token.DeepClone();
}
}
// key 转 camelCase
private static string ToCamelCase(string str)
{
if (string.IsNullOrEmpty(str)) return str;
return char.ToLower(str[0], CultureInfo.InvariantCulture) + str.Substring(1);
}
}
}
详细讲解
最新发布