305 lines
11 KiB
C#
305 lines
11 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// 服务商接口
|
||
/// </summary>
|
||
[ApiExplorerSettings(GroupName = "接口服务")]
|
||
public class ServiceProviderInterfaceService : ApplicationService
|
||
{
|
||
private ParameterService ParameterService => LazyServiceProvider.GetRequiredService<ParameterService>();
|
||
|
||
private FormParameterService FormParameterService =>
|
||
LazyServiceProvider.GetRequiredService<FormParameterService>();
|
||
|
||
private IInterfaceRepository InterfaceRepository =>
|
||
LazyServiceProvider.GetRequiredService<IInterfaceRepository>();
|
||
|
||
private IBasicRepository<ServiceProviderEntity> ServiceProviderRepository =>
|
||
LazyServiceProvider.GetRequiredService<IBasicRepository<ServiceProviderEntity>>();
|
||
|
||
private IBasicRepository<InterfaceMapEntity> InterfaceMapRepository =>
|
||
LazyServiceProvider.GetRequiredService<IBasicRepository<InterfaceMapEntity>>();
|
||
|
||
private InterfaceCategoryService InterfaceCategoryService =>
|
||
LazyServiceProvider.GetRequiredService<InterfaceCategoryService>();
|
||
|
||
|
||
/// <summary>
|
||
/// 服务商接口树形列表
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("Interface/GetServiceProviderInterfaceTreeListAsync")]
|
||
public async Task<List<CategoryTreeNode<ServiceProviderInterfaceTreeListOutputValueObject>>>
|
||
GetServiceProviderInterfaceTreeListAsync(ServiceProviderInterfaceTreeListInputObjectValue input)
|
||
{
|
||
var res = await InterfaceRepository.GetServiceProviderInterfaceListAsync(input);
|
||
|
||
var tree = await InterfaceCategoryService.GetCategoryTree(false, res);
|
||
|
||
return tree;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 服务商接口分页列表
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("Interface/ServiceProviderInterfacePaginatedList")]
|
||
public async Task<PagedResult<ServiceProviderInterfacePaginatedOutputValueObject>>
|
||
ServiceProviderInterfacePaginatedListAsync(ServiceProviderInterfacePaginatedInputObjectValue input)
|
||
{
|
||
return await InterfaceRepository.GetServiceProviderInterfacePaginatedListAsync(input);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取服务商接口下拉列表
|
||
/// </summary>
|
||
/// <param name="serviceProviderId">服务商id</param>
|
||
/// <returns></returns>
|
||
[HttpGet("Interface/GetServiceProviderInterfaceDropdownList")]
|
||
public async Task<List<ServiceProviderInterfaceDropdownListItem>> 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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取服务商接口明细
|
||
/// </summary>
|
||
/// <param name="id">服务商接口id</param>
|
||
/// <returns></returns>
|
||
[HttpGet("Interface/GetServiceProviderInterfaceById")]
|
||
public async Task<ServiceProviderInterfaceOutput> 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, ServiceProviderInterfaceOutput>(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;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 保存服务商接口
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 用OptionType来区分操作目的,1:新增,2:删除,3:修改
|
||
///<para>tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系</para>
|
||
/// </remarks>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessException"></exception>
|
||
[HttpPost("Interface/SaveServiceProviderInterface")]
|
||
public async Task<int> SaveServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input)
|
||
{
|
||
switch (input.OptionType)
|
||
{
|
||
case OptionType.新增:
|
||
return await CreateServiceProviderInterfaceAsync(input);
|
||
case OptionType.修改:
|
||
await UpdateServiceProviderInterfaceAsync(input);
|
||
break;
|
||
case OptionType.删除:
|
||
await BatchDeleteServiceProviderInterfaceByIdsAsync(new List<int> { input.Id ?? 0 });
|
||
break;
|
||
case OptionType.无:
|
||
break;
|
||
default:
|
||
throw new ArgumentOutOfRangeException();
|
||
}
|
||
|
||
return input.Id ?? 0;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 批量删除服务商接口
|
||
/// </summary>
|
||
/// <param name="ids">服务商接口id集合</param>
|
||
/// <returns></returns>
|
||
[HttpPost("Interface/BatchDeleteServiceProviderInterfaceByIds")]
|
||
public async Task<bool> BatchDeleteServiceProviderInterfaceByIdsAsync([FromBody] List<int> 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<int> CreateServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input)
|
||
{
|
||
// 校验参数合法性
|
||
ParameterService.ValidateParameter(
|
||
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
||
JsonConvert.SerializeObject(input.InParameterList))!);
|
||
ParameterService.ValidateParameter(
|
||
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
||
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<ServiceProviderInterfaceInput, InterfaceEntity>(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<string> 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<ServiceProviderInterfaceInput, InterfaceEntity>(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();
|
||
}
|
||
} |