using System.ComponentModel.DataAnnotations; using System.Diagnostics; using Newtonsoft.Json; using InterfaceForward.Application.Contracts.Dtos.Interface; using InterfaceForward.Application.Helpers; using InterfaceForward.Application.Services.Parameter; using InterfaceForward.Domain.Shared.Enum; using InterfaceForward.Repositories; using InterfaceForward.Repositories.Interface.Entitys; using InterfaceForward.Repositories.Interface.Services; using InterfaceForward.Repositories.Interface.ValueObjects; using InterfaceForward.Repositories.ServiceProvider.Entitys; using Microsoft.AspNetCore.Mvc; namespace InterfaceForward.Application.Services.Interface; /// /// 服务商接口 /// [ApiExplorerSettings(GroupName = "接口服务")] public class ServiceProviderInterfaceService : ApplicationService { private ParameterService ParameterService => LazyServiceProvider.GetRequiredService(); private FormParameterService FormParameterService => LazyServiceProvider.GetRequiredService(); private IInterfaceRepository InterfaceRepository => LazyServiceProvider.GetRequiredService(); private IBasicRepository ServiceProviderRepository => LazyServiceProvider.GetRequiredService>(); private IBasicRepository InterfaceMapRepository => LazyServiceProvider.GetRequiredService>(); private InterfaceCategoryService InterfaceCategoryService => LazyServiceProvider.GetRequiredService(); /// /// 服务商接口树形列表 /// /// /// [HttpPost("Interface/GetServiceProviderInterfaceTreeListAsync")] public async Task>> GetServiceProviderInterfaceTreeListAsync(ServiceProviderInterfaceTreeListInputObjectValue input) { var res = await InterfaceRepository.GetServiceProviderInterfaceListAsync(input); var tree = await InterfaceCategoryService.GetCategoryTree(false, res); return tree; } /// /// 服务商接口分页列表 /// /// /// [HttpPost("Interface/ServiceProviderInterfacePaginatedList")] public async Task> ServiceProviderInterfacePaginatedListAsync(ServiceProviderInterfacePaginatedInputObjectValue input) { return await InterfaceRepository.GetServiceProviderInterfacePaginatedListAsync(input); } /// /// 获取服务商接口下拉列表 /// /// 服务商id /// [HttpGet("Interface/GetServiceProviderInterfaceDropdownList")] public async Task> GetServiceProviderInterfaceDropdownListAsync( [Required] int serviceProviderId) { var res = await InterfaceRepository.GetListAsync(x => x.ServiceProviderId == serviceProviderId, x => new { x.Id, x.Code, x.Name }); return res.Select(x => new ServiceProviderInterfaceDropdownListItem { Id = x.Id, Name = x.Name, Code = x.Code }).ToList(); } /// /// 获取服务商接口明细 /// /// 服务商接口id /// [HttpGet("Interface/GetServiceProviderInterfaceById")] public async Task GetServiceProviderInterfaceByIdAsync([Required] int id) { // 接口基本信息 var interfaceEntity = await InterfaceRepository.GetFirstAsync(x => x.Id == id && !x.IsUpStream); if (interfaceEntity == null) { throw new BusinessException(message: "服务商接口不存在"); } var res = ObjectMapper.Map(interfaceEntity); // 构造参数 var paras = await InterfaceRepository.GetParameterListByIdAsync(id); // 入参树形列表 res.InParameterList = paras.Where(x => x.IsInPara).ToList(); // 出参树形列表 res.OutParameterList = paras.Where(x => !x.IsInPara).ToList(); // 表单列表 res.FormParameterList = await FormParameterService.GetParameterListAsync(id); return res; } /// /// 保存服务商接口 /// /// /// 用OptionType来区分操作目的,1:新增,2:删除,3:修改 ///tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 /// /// /// /// [HttpPost("Interface/SaveServiceProviderInterface")] public async Task SaveServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input) { switch (input.OptionType) { case OptionType.新增: return await CreateServiceProviderInterfaceAsync(input); case OptionType.修改: await UpdateServiceProviderInterfaceAsync(input); break; case OptionType.删除: await BatchDeleteServiceProviderInterfaceByIdsAsync(new List { input.Id ?? 0 }); break; case OptionType.无: break; default: throw new ArgumentOutOfRangeException(); } return input.Id ?? 0; } /// /// 批量删除服务商接口 /// /// 服务商接口id集合 /// [HttpPost("Interface/BatchDeleteServiceProviderInterfaceByIds")] public async Task BatchDeleteServiceProviderInterfaceByIdsAsync([FromBody] List ids) { using var tran = TransacationHelper.GetReadCommitted(); // 删除接口 await InterfaceRepository.SoftDeleteAsync(x => !x.IsUpStream && ids.Contains(x.Id)); // 删除接口映射 var mapIds = await InterfaceMapRepository.GetListAsync(x => ids.Contains(x.DownStreamId), x => x.Id); if (mapIds.Count > 0) { await InterfaceMapRepository.SoftDeleteAsync(x => mapIds.Contains(x.Id)); } tran.Complete(); return true; } internal async Task CreateServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input) { // 校验参数合法性 ParameterService.ValidateParameter( JsonConvert.DeserializeObject>( JsonConvert.SerializeObject(input.InParameterList))!); ParameterService.ValidateParameter( JsonConvert.DeserializeObject>( JsonConvert.SerializeObject(input.OutParameterList))!); /* * 1.校验业务逻辑 * 接口名唯一性,接口简码唯一性,请求地址唯一性 * 2.清洗数据结构 * 参数合并,参数合法性,参数扁平化bfs * 3.数据持久化 * 由于业务的观测粒度是保存行为(即取消不做任何数据保存),因此保持行为可以直接覆盖上次行为,注意事务 */ #region 校验业务逻辑 if (await InterfaceRepository.IsAnyAsync(x => !x.IsUpStream && x.Name.Equals(input.Name) && x.ServiceProviderId == input.ServiceProviderId)) { throw new BusinessException(message: $"接口名:{input.Name} 已存在"); } #endregion var interfaceEntity = ObjectMapper.Map(input); interfaceEntity.IsUpStream = false; // 开启事务 using var ts = TransacationHelper.GetReadCommitted(); // step1、生成接口编码 interfaceEntity.Code = await GenerateServiceProviderInterfaceCode(input.ServiceProviderId); // step2、持久化接口 var interfaceId = await InterfaceRepository.InsertReturnIdentityAsync(interfaceEntity); // 接口代码生成时并发兜底方案 if (await InterfaceRepository.CountAsync(x => x.Code.Equals(interfaceEntity.Code)) > 1) { throw new BusinessException(message: "接口代码生成异常,请稍后重试"); } // step3、持久化参数 await ParameterService.CreateParametersAsync(input.InParameterList, interfaceId, true); await ParameterService.CreateParametersAsync(input.OutParameterList, interfaceId, false); // step4、持久化表单参数 if (input.FormParameterList.Count > 0) { await FormParameterService.CreateParametersAsync(input.FormParameterList, interfaceId); } // 提交事务 ts.Complete(); return interfaceId; } private async Task GenerateServiceProviderInterfaceCode(int serviceProviderId) { // 系统生成,由服务商代码+3位数字组成(0-999按顺序生成) // tips:唯一性 var entity = await ServiceProviderRepository.GetFirstAsync(x => x.Id == serviceProviderId); if (entity == null) throw new BusinessException(message: "服务商不存在"); string res = entity.Code; // tips:要考虑并发 var code = await InterfaceRepository.GetCurrentCodeBySpId(serviceProviderId); int count = 0; if (!string.IsNullOrEmpty(code)) count = int.Parse(code.Substring(code.Length - 3, 3)); res += (count + 1).ToString().PadLeft(3, '0'); return res; } private async Task UpdateServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input) { #region 校验业务逻辑 if (!await InterfaceRepository.IsAnyAsync(x => x.Id == input.Id)) { throw new BusinessException(message: "服务商接口不存在"); } if (await InterfaceRepository.IsAnyAsync(x => x.Name.Equals(input.Name) && x.Id != input.Id && !x.IsUpStream && x.ServiceProviderId == input.ServiceProviderId)) { throw new BusinessException(message: $"接口名:{input.Name} 已存在"); } #endregion Debug.Assert(input.Id != null, $"{input.Id} 不能为空"); var interfaceEntity = ObjectMapper.Map(input); // 开启事务 using var ts = TransacationHelper.GetReadCommitted(); // step1、更新接口 await InterfaceRepository.UpdateAsync(interfaceEntity, x => new { x.Code, x.IsUpStream, x.ServiceProviderId, x.CreateTime, x.CreateUserId, x.IsDeleted }); // step2、维护参数(增删改) await ParameterService.MaintainParametersAsync(input.InParameterList, (int)input.Id, true); await ParameterService.MaintainParametersAsync(input.OutParameterList, (int)input.Id, false); // step3、更新表单参数 await FormParameterService.MaintainParametersAsync(input.FormParameterList, interfaceEntity.Id); // 提交事务 ts.Complete(); } }