feat:重构
This commit is contained in:
parent
432ea493d0
commit
d70c9545a6
@ -42,6 +42,11 @@ namespace InterfaceForward.Application.Contracts.Dtos.Interface
|
|||||||
///</summary>
|
///</summary>
|
||||||
public ParameterType Type { get; set; }
|
public ParameterType Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参数用途
|
||||||
|
/// </summary>
|
||||||
|
public ParameterParaKind ParaKind { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否必填
|
/// 是否必填
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -106,17 +106,37 @@ public class SaveInterfaceInput
|
|||||||
public ParameterType? MappedParamType { get; set; }
|
public ParameterType? MappedParamType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 入参列表
|
/// 上游入参列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ParameterInput> InParameterList { get; set; } = new();
|
public List<ParameterInput> InParameterList { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Json/Xml 请求体参数树
|
||||||
|
/// </summary>
|
||||||
|
public List<ParameterInput> RequestBodyParameterList { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Form 类映射体参数树
|
||||||
|
/// </summary>
|
||||||
|
public List<ParameterInput> MappingBodyParameterList { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 出参列表
|
/// 出参列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ParameterInput> OutParameterList { get; set; } = new();
|
public List<ParameterInput> OutParameterList { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表单列表
|
/// Query KV 列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<FormParameterInput> FormParameterList { get; set; } = new();
|
public List<FormParameterInput> QueryFormParameterList { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header KV 列表
|
||||||
|
/// </summary>
|
||||||
|
public List<FormParameterInput> HeaderFormParameterList { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Body Form KV 列表
|
||||||
|
/// </summary>
|
||||||
|
public List<FormParameterInput> BodyFormParameterList { get; set; } = new();
|
||||||
}
|
}
|
||||||
@ -31,6 +31,16 @@ public class ForwardCoreContext
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<InterfaceFormFieldDto> FormFieldList { get; set; } = [];
|
public List<InterfaceFormFieldDto> FormFieldList { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query 字段列表
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceFormFieldDto> QueryFieldList { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header 字段列表
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceFormFieldDto> HeaderFieldList { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 入参映射列表(树形结构)
|
/// 入参映射列表(树形结构)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -279,6 +279,12 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
// 将参数绑定到query
|
// 将参数绑定到query
|
||||||
var builder = new UriBuilder(targetInterface.RequestAddress);
|
var builder = new UriBuilder(targetInterface.RequestAddress);
|
||||||
var query = HttpUtility.ParseQueryString(builder.Query);
|
var query = HttpUtility.ParseQueryString(builder.Query);
|
||||||
|
foreach (var item in context.QueryFieldList)
|
||||||
|
{
|
||||||
|
query.Remove(item.Name);
|
||||||
|
query.Add(item.Name, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in context.FixedFieldList.Where(x => x.FieldPosition == FieldPosition.Query))
|
foreach (var item in context.FixedFieldList.Where(x => x.FieldPosition == FieldPosition.Query))
|
||||||
{
|
{
|
||||||
query.Remove(item.FieldName);
|
query.Remove(item.FieldName);
|
||||||
@ -293,6 +299,16 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
SetContentType(context, msg);
|
SetContentType(context, msg);
|
||||||
|
|
||||||
// 将参数绑定到header
|
// 将参数绑定到header
|
||||||
|
foreach (var item in context.HeaderFieldList)
|
||||||
|
{
|
||||||
|
if (msg.Headers.Contains(item.Name))
|
||||||
|
msg.Headers.Remove(item.Name);
|
||||||
|
if (!msg.Headers.TryAddWithoutValidation(item.Name, item.Value))
|
||||||
|
{
|
||||||
|
ThrowBusinessException(context, $"请求头无法插入 {item.Name}:{item.Value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in context.FixedFieldList.Where(x => x.FieldPosition == FieldPosition.Header))
|
foreach (var item in context.FixedFieldList.Where(x => x.FieldPosition == FieldPosition.Header))
|
||||||
{
|
{
|
||||||
//msg.Content.Headers.TryAddWithoutValidation(item.FieldName, item.FieldValue);
|
//msg.Content.Headers.TryAddWithoutValidation(item.FieldName, item.FieldValue);
|
||||||
@ -399,7 +415,7 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
Dictionary<string, string> nameValueCollection;
|
Dictionary<string, string> nameValueCollection;
|
||||||
if (context.FormFieldList.Count != 0)
|
if (context.FormFieldList.Count != 0)
|
||||||
{
|
{
|
||||||
var field = context.FormFieldList.FirstOrDefault(x => x.Value == GlobalConst.FromBody);
|
var field = context.FormFieldList.FirstOrDefault(x => x.Value == GlobalConst.FromMappingBody);
|
||||||
if (field != null) field.Value = body;
|
if (field != null) field.Value = body;
|
||||||
nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value);
|
nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value);
|
||||||
}
|
}
|
||||||
@ -504,19 +520,20 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单
|
// Query / Header / 表单
|
||||||
|
foreach (var item in context.QueryFieldList)
|
||||||
|
{
|
||||||
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in context.HeaderFieldList)
|
||||||
|
{
|
||||||
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in context.FormFieldList)
|
foreach (var item in context.FormFieldList)
|
||||||
{
|
{
|
||||||
item.Value = item.Value switch
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
{
|
|
||||||
GlobalConst.TimeStamp => item.Description == "ms"
|
|
||||||
? timeStamp.ToString()
|
|
||||||
: (timeStamp / 1000).ToString(), // s
|
|
||||||
GlobalConst.DateTime => TurnDate(now, item.Description),
|
|
||||||
GlobalConst.Url => context.TargetInterface.RequestAddress,
|
|
||||||
GlobalConst.FromAccount => context.GetAccountFieldValueOrNull(item.Name) ?? string.Empty,
|
|
||||||
_ => item.Value // 不处理
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绑定body部分的字段
|
// 绑定body部分的字段
|
||||||
@ -551,6 +568,21 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
return dateTime.ToString(GlobalConst.DefaultDateStyle);
|
return dateTime.ToString(GlobalConst.DefaultDateStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ReplaceFormPlaceholder(string name, string value, string? description)
|
||||||
|
{
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
GlobalConst.TimeStamp => description == "ms"
|
||||||
|
? timeStamp.ToString()
|
||||||
|
: (timeStamp / 1000).ToString(),
|
||||||
|
GlobalConst.DateTime => TurnDate(now, description),
|
||||||
|
GlobalConst.Url => context.TargetInterface.RequestAddress,
|
||||||
|
GlobalConst.FromAccount => context.GetAccountFieldValueOrNull(name) ?? string.Empty,
|
||||||
|
GlobalConst.FromMappingBody => GlobalConst.FromMappingBody,
|
||||||
|
_ => value
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplaceCore(JToken obj, string path, JToken value)
|
void ReplaceCore(JToken obj, string path, JToken value)
|
||||||
|
|||||||
@ -109,12 +109,22 @@ public class InterfaceService : ApplicationService
|
|||||||
// 构造参数
|
// 构造参数
|
||||||
var paras = await InterfaceRepository.GetParameterListByIdAsync(id);
|
var paras = await InterfaceRepository.GetParameterListByIdAsync(id);
|
||||||
// 入参树形列表
|
// 入参树形列表
|
||||||
res.InParameterList = paras.Where(x => x.IsInPara).ToList();
|
res.InParameterList = interfaceEntity.IsUpStream
|
||||||
|
? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList()
|
||||||
|
: [];
|
||||||
|
res.RequestBodyParameterList = !interfaceEntity.IsUpStream && interfaceEntity.ContentType is ContentType.Json or ContentType.Xml
|
||||||
|
? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList()
|
||||||
|
: [];
|
||||||
|
res.MappingBodyParameterList = !interfaceEntity.IsUpStream && interfaceEntity.ContentType == ContentType.FormUrlEncoded
|
||||||
|
? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.MappingBody).ToList()
|
||||||
|
: [];
|
||||||
// 出参树形列表
|
// 出参树形列表
|
||||||
res.OutParameterList = paras.Where(x => !x.IsInPara).ToList();
|
res.OutParameterList = paras.Where(x => !x.IsInPara).ToList();
|
||||||
|
|
||||||
// 表单列表
|
// 表单列表
|
||||||
res.FormParameterList = await FormParameterService.GetParameterListAsync(id);
|
res.QueryFormParameterList = await FormParameterService.GetParameterListAsync(id, FieldPosition.Query);
|
||||||
|
res.HeaderFormParameterList = await FormParameterService.GetParameterListAsync(id, FieldPosition.Header);
|
||||||
|
res.BodyFormParameterList = await FormParameterService.GetParameterListAsync(id, FieldPosition.Body);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -133,16 +143,9 @@ public class InterfaceService : ApplicationService
|
|||||||
[HttpPost("Interface/SaveInterface")]
|
[HttpPost("Interface/SaveInterface")]
|
||||||
public async Task<int> SaveInterfaceAsync(SaveInterfaceInput input)
|
public async Task<int> SaveInterfaceAsync(SaveInterfaceInput input)
|
||||||
{
|
{
|
||||||
input.InParameterList.ForEach(x =>
|
NormalizeRootArrayName(GetInputParameterList(input));
|
||||||
{
|
NormalizeRootArrayName(input.OutParameterList);
|
||||||
if (x.PId == 0 && x.Type == ParameterType.Array && x.Name == GlobalConst.RootParameterName)
|
ValidateBodyLists(input);
|
||||||
x.Name = string.Empty;
|
|
||||||
});
|
|
||||||
input.OutParameterList.ForEach(x =>
|
|
||||||
{
|
|
||||||
if (x.PId == 0 && x.Type == ParameterType.Array && x.Name == GlobalConst.RootParameterName)
|
|
||||||
x.Name = string.Empty;
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (input.OptionType)
|
switch (input.OptionType)
|
||||||
{
|
{
|
||||||
@ -209,7 +212,7 @@ public class InterfaceService : ApplicationService
|
|||||||
// 校验参数合法性
|
// 校验参数合法性
|
||||||
ParameterService.ValidateParameter(
|
ParameterService.ValidateParameter(
|
||||||
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
||||||
JsonConvert.SerializeObject(input.InParameterList))!);
|
JsonConvert.SerializeObject(GetInputParameterList(input)))!);
|
||||||
ParameterService.ValidateParameter(
|
ParameterService.ValidateParameter(
|
||||||
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
JsonConvert.DeserializeObject<List<ParameterInput>>(
|
||||||
JsonConvert.SerializeObject(input.OutParameterList))!);
|
JsonConvert.SerializeObject(input.OutParameterList))!);
|
||||||
@ -248,11 +251,11 @@ public class InterfaceService : ApplicationService
|
|||||||
var interfaceId = await InterfaceRepository.InsertReturnIdentityAsync(interfaceEntity);
|
var interfaceId = await InterfaceRepository.InsertReturnIdentityAsync(interfaceEntity);
|
||||||
|
|
||||||
// 持久化参数
|
// 持久化参数
|
||||||
await ParameterService.CreateParametersAsync(input.InParameterList, interfaceId, true);
|
await CreateInputParametersAsync(input, interfaceId);
|
||||||
await ParameterService.CreateParametersAsync(input.OutParameterList, interfaceId, false);
|
await ParameterService.CreateParametersAsync(input.OutParameterList, interfaceId, false);
|
||||||
|
|
||||||
// 持久化表单参数
|
// 持久化表单参数
|
||||||
await FormParameterService.CreateParametersAsync(input.FormParameterList, interfaceId);
|
await CreateFormParametersAsync(input, interfaceId);
|
||||||
|
|
||||||
// 接口代码生成时并发兜底方案
|
// 接口代码生成时并发兜底方案
|
||||||
if (await InterfaceRepository.CountAsync(x => x.Code.Equals(interfaceEntity.Code)) > 1)
|
if (await InterfaceRepository.CountAsync(x => x.Code.Equals(interfaceEntity.Code)) > 1)
|
||||||
@ -321,14 +324,119 @@ public class InterfaceService : ApplicationService
|
|||||||
});
|
});
|
||||||
|
|
||||||
// step2、维护参数(增删改)
|
// step2、维护参数(增删改)
|
||||||
await ParameterService.MaintainParametersAsync(input.InParameterList, (int)input.Id, true);
|
await MaintainInputParametersAsync(input, (int)input.Id);
|
||||||
|
|
||||||
await ParameterService.MaintainParametersAsync(input.OutParameterList, (int)input.Id, false);
|
await ParameterService.MaintainParametersAsync(input.OutParameterList, (int)input.Id, false);
|
||||||
|
|
||||||
// step3、更新表单参数
|
// step3、更新表单参数
|
||||||
await FormParameterService.MaintainParametersAsync(input.FormParameterList, interfaceEntity.Id);
|
await MaintainFormParametersAsync(input, interfaceEntity.Id);
|
||||||
|
|
||||||
// 提交事务
|
// 提交事务
|
||||||
ts.Complete();
|
ts.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<ParameterInput> GetInputParameterList(SaveInterfaceInput input)
|
||||||
|
{
|
||||||
|
if (input.IsUpStream) return input.InParameterList;
|
||||||
|
return input.ContentType switch
|
||||||
|
{
|
||||||
|
ContentType.Json or ContentType.Xml => input.RequestBodyParameterList,
|
||||||
|
ContentType.FormUrlEncoded => input.MappingBodyParameterList,
|
||||||
|
_ => []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void NormalizeRootArrayName(List<ParameterInput> list)
|
||||||
|
{
|
||||||
|
list.ForEach(x =>
|
||||||
|
{
|
||||||
|
if (x.PId == 0 && x.Type == ParameterType.Array && x.Name == GlobalConst.RootParameterName)
|
||||||
|
x.Name = string.Empty;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateBodyLists(SaveInterfaceInput input)
|
||||||
|
{
|
||||||
|
if (input.IsUpStream)
|
||||||
|
{
|
||||||
|
if (input.RequestBodyParameterList.Count > 0 || input.MappingBodyParameterList.Count > 0 || input.BodyFormParameterList.Count > 0)
|
||||||
|
throw new BusinessException(message: "上游接口只能维护 inParameterList");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input.ContentType)
|
||||||
|
{
|
||||||
|
case ContentType.Json:
|
||||||
|
case ContentType.Xml:
|
||||||
|
if (input.InParameterList.Count > 0 || input.MappingBodyParameterList.Count > 0 || input.BodyFormParameterList.Count > 0)
|
||||||
|
throw new BusinessException(message: "Json/Xml 下游接口只能维护 requestBodyParameterList");
|
||||||
|
break;
|
||||||
|
case ContentType.FormUrlEncoded:
|
||||||
|
if (input.InParameterList.Count > 0 || input.RequestBodyParameterList.Count > 0)
|
||||||
|
throw new BusinessException(message: "FormUrlEncoded 下游接口只能维护 bodyFormParameterList 和 mappingBodyParameterList");
|
||||||
|
break;
|
||||||
|
case ContentType.FormData:
|
||||||
|
throw new BusinessException(message: "暂时不支持该ContentType");
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CreateInputParametersAsync(SaveInterfaceInput input, int interfaceId)
|
||||||
|
{
|
||||||
|
if (input.IsUpStream)
|
||||||
|
{
|
||||||
|
await ParameterService.CreateParametersAsync(input.InParameterList, interfaceId, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input.ContentType)
|
||||||
|
{
|
||||||
|
case ContentType.Json:
|
||||||
|
case ContentType.Xml:
|
||||||
|
await ParameterService.CreateParametersAsync(input.RequestBodyParameterList, interfaceId, true);
|
||||||
|
break;
|
||||||
|
case ContentType.FormUrlEncoded:
|
||||||
|
await ParameterService.CreateParametersAsync(input.MappingBodyParameterList, interfaceId, true,
|
||||||
|
ParameterParaKind.MappingBody);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MaintainInputParametersAsync(SaveInterfaceInput input, int interfaceId)
|
||||||
|
{
|
||||||
|
if (input.IsUpStream)
|
||||||
|
{
|
||||||
|
await ParameterService.MaintainParametersAsync(input.InParameterList, interfaceId, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input.ContentType)
|
||||||
|
{
|
||||||
|
case ContentType.Json:
|
||||||
|
case ContentType.Xml:
|
||||||
|
await ParameterService.MaintainParametersAsync(input.RequestBodyParameterList, interfaceId, true);
|
||||||
|
break;
|
||||||
|
case ContentType.FormUrlEncoded:
|
||||||
|
await ParameterService.MaintainParametersAsync(input.MappingBodyParameterList, interfaceId, true,
|
||||||
|
ParameterParaKind.MappingBody);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CreateFormParametersAsync(SaveInterfaceInput input, int interfaceId)
|
||||||
|
{
|
||||||
|
await FormParameterService.CreateParametersAsync(input.QueryFormParameterList, interfaceId, FieldPosition.Query);
|
||||||
|
await FormParameterService.CreateParametersAsync(input.HeaderFormParameterList, interfaceId, FieldPosition.Header);
|
||||||
|
if (!input.IsUpStream && input.ContentType == ContentType.FormUrlEncoded)
|
||||||
|
await FormParameterService.CreateParametersAsync(input.BodyFormParameterList, interfaceId, FieldPosition.Body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MaintainFormParametersAsync(SaveInterfaceInput input, int interfaceId)
|
||||||
|
{
|
||||||
|
await FormParameterService.MaintainParametersAsync(input.QueryFormParameterList, interfaceId, FieldPosition.Query);
|
||||||
|
await FormParameterService.MaintainParametersAsync(input.HeaderFormParameterList, interfaceId, FieldPosition.Header);
|
||||||
|
if (!input.IsUpStream && input.ContentType == ContentType.FormUrlEncoded)
|
||||||
|
await FormParameterService.MaintainParametersAsync(input.BodyFormParameterList, interfaceId, FieldPosition.Body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -105,6 +105,8 @@ public class InterfaceForwardCommon(
|
|||||||
AccountFieldList = accountFieldCache,
|
AccountFieldList = accountFieldCache,
|
||||||
ReturnConfigList = item.ReturnConfigList,
|
ReturnConfigList = item.ReturnConfigList,
|
||||||
FormFieldList = item.FormFieldList,
|
FormFieldList = item.FormFieldList,
|
||||||
|
QueryFieldList = item.QueryFieldList,
|
||||||
|
HeaderFieldList = item.HeaderFieldList,
|
||||||
InParamTreeList = item.InParamTreeList,
|
InParamTreeList = item.InParamTreeList,
|
||||||
PrefixScript = item.PrefixScript,
|
PrefixScript = item.PrefixScript,
|
||||||
PostfixScript = item.PostfixScript,
|
PostfixScript = item.PostfixScript,
|
||||||
@ -192,7 +194,9 @@ public class InterfaceForwardCommon(
|
|||||||
PrefixScript = interfaceDto.PrefixScript,
|
PrefixScript = interfaceDto.PrefixScript,
|
||||||
PostfixScript = interfaceDto.PostfixScript,
|
PostfixScript = interfaceDto.PostfixScript,
|
||||||
OriginalInterfaceInput = body,
|
OriginalInterfaceInput = body,
|
||||||
FormFieldList = interfaceDto.FormFieldList // normal case is null
|
FormFieldList = interfaceDto.FormFieldList,
|
||||||
|
QueryFieldList = interfaceDto.QueryFieldList,
|
||||||
|
HeaderFieldList = interfaceDto.HeaderFieldList
|
||||||
};
|
};
|
||||||
authContext.ServiceProviderRequestLog = new RequestLogDto(logRepository.AppRequestLog.RequestId)
|
authContext.ServiceProviderRequestLog = new RequestLogDto(logRepository.AppRequestLog.RequestId)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -27,9 +27,10 @@ public class FormParameterService : ApplicationService
|
|||||||
/// <param name="interfaceId">接口id</param>
|
/// <param name="interfaceId">接口id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet("FormParameter/GetParameterList")]
|
[HttpGet("FormParameter/GetParameterList")]
|
||||||
public async Task<List<FormParameterItem>> GetParameterListAsync([Required] int interfaceId)
|
public async Task<List<FormParameterItem>> GetParameterListAsync([Required] int interfaceId, FieldPosition? fieldPosition = null)
|
||||||
{
|
{
|
||||||
var formList = await _formParameterRepository.GetListAsync(x => x.InterfaceId == interfaceId);
|
var formList = await _formParameterRepository.GetListAsync(x =>
|
||||||
|
x.InterfaceId == interfaceId && (fieldPosition == null || x.FieldPosition == fieldPosition));
|
||||||
return ObjectMapper.Map<List<FormParameterEntity>, List<FormParameterItem>>(formList);
|
return ObjectMapper.Map<List<FormParameterEntity>, List<FormParameterItem>>(formList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,9 +39,10 @@ public class FormParameterService : ApplicationService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
/// <param name="interfaceId">接口id</param>
|
/// <param name="interfaceId">接口id</param>
|
||||||
internal async Task CreateParametersAsync(List<FormParameterInput> list, int interfaceId)
|
internal async Task CreateParametersAsync(List<FormParameterInput> list, int interfaceId, FieldPosition fieldPosition)
|
||||||
{
|
{
|
||||||
if (list.Count <= 0) return;
|
if (list.Count <= 0) return;
|
||||||
|
list.ForEach(x => x.FieldPosition = fieldPosition);
|
||||||
var formEntities = ObjectMapper.Map<List<FormParameterInput>, List<FormParameterEntity>>(list);
|
var formEntities = ObjectMapper.Map<List<FormParameterInput>, List<FormParameterEntity>>(list);
|
||||||
formEntities.ForEach(x => x.InterfaceId = interfaceId);
|
formEntities.ForEach(x => x.InterfaceId = interfaceId);
|
||||||
await _formParameterRepository.InsertRangeAsync(formEntities);
|
await _formParameterRepository.InsertRangeAsync(formEntities);
|
||||||
@ -51,9 +53,10 @@ public class FormParameterService : ApplicationService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
/// <param name="interfaceId">接口id</param>
|
/// <param name="interfaceId">接口id</param>
|
||||||
internal async Task MaintainParametersAsync(List<FormParameterInput> list, int interfaceId)
|
internal async Task MaintainParametersAsync(List<FormParameterInput> list, int interfaceId, FieldPosition fieldPosition)
|
||||||
{
|
{
|
||||||
if (list.Count == 0) return;
|
if (list.Count == 0) return;
|
||||||
|
list.ForEach(x => x.FieldPosition = fieldPosition);
|
||||||
|
|
||||||
using var ts = TransacationHelper.GetReadCommitted();
|
using var ts = TransacationHelper.GetReadCommitted();
|
||||||
|
|
||||||
@ -68,12 +71,12 @@ public class FormParameterService : ApplicationService
|
|||||||
.Where(x => x.OptionType == OptionType.修改).ToList());
|
.Where(x => x.OptionType == OptionType.修改).ToList());
|
||||||
await _formParameterRepository.UpdateRangeAsync(updEntities, x => new
|
await _formParameterRepository.UpdateRangeAsync(updEntities, x => new
|
||||||
{
|
{
|
||||||
x.Name, x.Value, x.Description
|
x.Name, x.Value, x.Description, x.FieldPosition
|
||||||
});
|
});
|
||||||
|
|
||||||
// 创建
|
// 创建
|
||||||
await CreateParametersAsync(list.Where(x => x.OptionType == OptionType.新增).ToList()
|
await CreateParametersAsync(list.Where(x => x.OptionType == OptionType.新增).ToList()
|
||||||
, interfaceId);
|
, interfaceId, fieldPosition);
|
||||||
|
|
||||||
ts.Complete();
|
ts.Complete();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,10 +48,10 @@ public class ParameterService : ApplicationService
|
|||||||
[HttpGet("Parameter/GetParameterList")]
|
[HttpGet("Parameter/GetParameterList")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<IEnumerable<InterfaceParameterOutputValueObject>> GetParameterListAsync([Required] bool isInPara,
|
public async Task<IEnumerable<InterfaceParameterOutputValueObject>> GetParameterListAsync([Required] bool isInPara,
|
||||||
[Required] int id, bool onlyLeafs = false)
|
[Required] int id, bool onlyLeafs = false, ParameterParaKind? paraKind = null)
|
||||||
{
|
{
|
||||||
var paras = await _interfaceRepository.GetParameterListByIdAsync(id, onlyLeafs);
|
var paras = await _interfaceRepository.GetParameterListByIdAsync(id, onlyLeafs);
|
||||||
return paras.Where(x => x.IsInPara == isInPara);
|
return paras.Where(x => x.IsInPara == isInPara && (paraKind == null || x.ParaKind == paraKind));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -287,11 +287,13 @@ public class ParameterService : ApplicationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal async Task<bool> MaintainParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara)
|
internal async Task<bool> MaintainParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara,
|
||||||
|
ParameterParaKind paraKind = ParameterParaKind.Normal)
|
||||||
{
|
{
|
||||||
#region 防止请求端没传入已存在的节点
|
#region 防止请求端没传入已存在的节点
|
||||||
|
|
||||||
var parameters = await _parameterRepository.GetParameterListByNameAsync(interfaceId, isInPara);
|
list.ForEach(x => x.ParaKind = paraKind);
|
||||||
|
var parameters = await _parameterRepository.GetParameterListByNameAsync(interfaceId, isInPara, paraKind);
|
||||||
foreach (var item in parameters)
|
foreach (var item in parameters)
|
||||||
{
|
{
|
||||||
if (list.All(x => x.Id != item.Id))
|
if (list.All(x => x.Id != item.Id))
|
||||||
@ -307,9 +309,9 @@ public class ParameterService : ApplicationService
|
|||||||
using var ts = TransacationHelper.GetReadCommitted();
|
using var ts = TransacationHelper.GetReadCommitted();
|
||||||
|
|
||||||
// 创建
|
// 创建
|
||||||
await CreateParametersAsync(list.Where(x => x.OptionType == OptionType.新增).ToList(), interfaceId, isInPara);
|
await CreateParametersAsync(list.Where(x => x.OptionType == OptionType.新增).ToList(), interfaceId, isInPara, paraKind);
|
||||||
// 更新
|
// 更新
|
||||||
await UpdateParametersAsync(list.Where(x => x.OptionType == OptionType.修改).ToList(), interfaceId, isInPara);
|
await UpdateParametersAsync(list.Where(x => x.OptionType == OptionType.修改).ToList(), interfaceId, isInPara, paraKind);
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
await DeleteParametersAsync(list.Where(x => x.OptionType == OptionType.删除).Select(x => x.Id).ToList());
|
await DeleteParametersAsync(list.Where(x => x.OptionType == OptionType.删除).Select(x => x.Id).ToList());
|
||||||
@ -328,11 +330,13 @@ public class ParameterService : ApplicationService
|
|||||||
/// <param name="interfaceId"></param>
|
/// <param name="interfaceId"></param>
|
||||||
/// <param name="isInPara"></param>
|
/// <param name="isInPara"></param>
|
||||||
/// <exception cref="BusinessException"></exception>
|
/// <exception cref="BusinessException"></exception>
|
||||||
internal async Task CreateParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara)
|
internal async Task CreateParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara,
|
||||||
|
ParameterParaKind paraKind = ParameterParaKind.Normal)
|
||||||
{
|
{
|
||||||
if (list.Count <= 0) return;
|
if (list.Count <= 0) return;
|
||||||
|
list.ForEach(x => x.ParaKind = paraKind);
|
||||||
var parameters =
|
var parameters =
|
||||||
await _parameterRepository.GetListAsync(x => x.InterfaceId == interfaceId && x.IsInPara == isInPara);
|
await _parameterRepository.GetListAsync(x => x.InterfaceId == interfaceId && x.IsInPara == isInPara && x.ParaKind == paraKind);
|
||||||
|
|
||||||
var tops = new List<ParameterInput>();
|
var tops = new List<ParameterInput>();
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
@ -368,6 +372,7 @@ public class ParameterService : ApplicationService
|
|||||||
entity.Alias = cur.Alias;
|
entity.Alias = cur.Alias;
|
||||||
entity.InterfaceId = interfaceId;
|
entity.InterfaceId = interfaceId;
|
||||||
entity.IsInPara = isInPara;
|
entity.IsInPara = isInPara;
|
||||||
|
entity.ParaKind = paraKind;
|
||||||
|
|
||||||
if (!cur.Sort.IsNullOrWhiteSpace())
|
if (!cur.Sort.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
@ -414,13 +419,14 @@ public class ParameterService : ApplicationService
|
|||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
/// <param name="interfaceId"></param>
|
/// <param name="interfaceId"></param>
|
||||||
/// <param name="isInPara"></param>
|
/// <param name="isInPara"></param>
|
||||||
private async Task UpdateParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara)
|
private async Task UpdateParametersAsync(List<ParameterInput> list, int interfaceId, bool isInPara,
|
||||||
|
ParameterParaKind paraKind)
|
||||||
{
|
{
|
||||||
if (list.Count == 0) return;
|
if (list.Count == 0) return;
|
||||||
Debug.Assert(!list.Any(x => x.Id < 1), "参数id均需大于0");
|
Debug.Assert(!list.Any(x => x.Id < 1), "参数id均需大于0");
|
||||||
|
|
||||||
var parameters =
|
var parameters =
|
||||||
await _parameterRepository.GetListAsync(x => x.InterfaceId == interfaceId && x.IsInPara == isInPara);
|
await _parameterRepository.GetListAsync(x => x.InterfaceId == interfaceId && x.IsInPara == isInPara && x.ParaKind == paraKind);
|
||||||
|
|
||||||
var treeList = BuildTreeList(parameters, ParameterRootId);
|
var treeList = BuildTreeList(parameters, ParameterRootId);
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,11 @@ public class FormParameterItem
|
|||||||
///</summary>
|
///</summary>
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 字段位置
|
||||||
|
///</summary>
|
||||||
|
public FieldPosition FieldPosition { get; set; }
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 参数描述
|
/// 参数描述
|
||||||
///</summary>
|
///</summary>
|
||||||
|
|||||||
@ -96,4 +96,14 @@ public class TargetInterfaceSummary
|
|||||||
/// 表单字段列表
|
/// 表单字段列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<InterfaceFormFieldDto> FormFieldList { get; set; } = [];
|
public List<InterfaceFormFieldDto> FormFieldList { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query 字段列表
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceFormFieldDto> QueryFieldList { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header 字段列表
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceFormFieldDto> HeaderFieldList { get; set; } = [];
|
||||||
}
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
namespace InterfaceForward.Domain.Shared.Enum;
|
||||||
|
|
||||||
|
public enum ParameterParaKind
|
||||||
|
{
|
||||||
|
Normal = 0,
|
||||||
|
MappingBody = 1
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ public static class GlobalConst
|
|||||||
{
|
{
|
||||||
public const string FromAccount = "$FromAccount";
|
public const string FromAccount = "$FromAccount";
|
||||||
public const string FromBody = "$FromBody";
|
public const string FromBody = "$FromBody";
|
||||||
|
public const string FromMappingBody = "$FromMappingBody";
|
||||||
public const string TimeStamp = "$TimeStamp";
|
public const string TimeStamp = "$TimeStamp";
|
||||||
public const string DateTime = "$DateTime";
|
public const string DateTime = "$DateTime";
|
||||||
public const string Url = "$Url";
|
public const string Url = "$Url";
|
||||||
|
|||||||
@ -90,17 +90,37 @@ public class InterfaceOutput
|
|||||||
public ParameterType? MappedParamType { get; set; }
|
public ParameterType? MappedParamType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 入参列表
|
/// 上游入参列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<InterfaceParameterOutputValueObject> InParameterList { get; set; }
|
public List<InterfaceParameterOutputValueObject> InParameterList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Json/Xml 请求体参数树
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceParameterOutputValueObject> RequestBodyParameterList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Form 类映射体参数树
|
||||||
|
/// </summary>
|
||||||
|
public List<InterfaceParameterOutputValueObject> MappingBodyParameterList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 出参列表
|
/// 出参列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<InterfaceParameterOutputValueObject> OutParameterList { get; set; }
|
public List<InterfaceParameterOutputValueObject> OutParameterList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表单列表
|
/// Query KV 列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<FormParameterItem> FormParameterList { get; set; }
|
public List<FormParameterItem> QueryFormParameterList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header KV 列表
|
||||||
|
/// </summary>
|
||||||
|
public List<FormParameterItem> HeaderFormParameterList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Body Form KV 列表
|
||||||
|
/// </summary>
|
||||||
|
public List<FormParameterItem> BodyFormParameterList { get; set; }
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ public class InterfaceForwardQuery : BasicRepository<FixedParameterEntity>, ISco
|
|||||||
/// <param name="isInParaMap">是入参映射</param>
|
/// <param name="isInParaMap">是入参映射</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<IReadOnlyCollection<InterfaceParameterMapDto>> GetParameterMapListAsync(List<int> mapIds,
|
public async Task<IReadOnlyCollection<InterfaceParameterMapDto>> GetParameterMapListAsync(List<int> mapIds,
|
||||||
bool isInParaMap)
|
bool isInParaMap, ParameterParaKind? paraKind = null)
|
||||||
{
|
{
|
||||||
// tips:这里要拿所有节点,而非仅叶子,因为要构建参数树
|
// tips:这里要拿所有节点,而非仅叶子,因为要构建参数树
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ ORDER BY `b`.`Sort` ASC
|
|||||||
select `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` ,
|
select `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` ,
|
||||||
{(isMultiMap ? "CONCAT(d.Code, '.', c.Alias)" : "c.Alias")} AS `MapAlias` , `b`.`IsRequired` AS `IsRequired` , t.FreeMap
|
{(isMultiMap ? "CONCAT(d.Code, '.', c.Alias)" : "c.Alias")} AS `MapAlias` , `b`.`IsRequired` AS `IsRequired` , t.FreeMap
|
||||||
from t_interface_map t
|
from t_interface_map t
|
||||||
LEFT JOIN `t_parameter` `b` ON {(isInParaMap ? "t.DownStreamId" : "t.UpStreamId")} = `b`.`InterfaceId` and b.IsInPara = {isInParaMap} AND ( `b`.`IsDeleted` = 0 )
|
LEFT JOIN `t_parameter` `b` ON {(isInParaMap ? "t.DownStreamId" : "t.UpStreamId")} = `b`.`InterfaceId` and b.IsInPara = {isInParaMap} {(paraKind == null ? string.Empty : $"and b.ParaKind = {(int)paraKind}")} AND ( `b`.`IsDeleted` = 0 )
|
||||||
Left JOIN `t_interface_map_detail` `a` ON ( `t`.`Id` = `a`.`InterfaceMapId` ) and b.id = a.ParaId and a.IsDeleted = 0
|
Left JOIN `t_interface_map_detail` `a` ON ( `t`.`Id` = `a`.`InterfaceMapId` ) and b.id = a.ParaId and a.IsDeleted = 0
|
||||||
Left JOIN `t_parameter` `c` ON ( `a`.`MappedParaId` = `c`.`Id` ) AND ( `c`.`IsDeleted` = 0 )
|
Left JOIN `t_parameter` `c` ON ( `a`.`MappedParaId` = `c`.`Id` ) AND ( `c`.`IsDeleted` = 0 )
|
||||||
Left JOIN t_interface d on c.interfaceid = d.id
|
Left JOIN t_interface d on c.interfaceid = d.id
|
||||||
@ -207,15 +207,20 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
|||||||
InParamTreeList = null,
|
InParamTreeList = null,
|
||||||
FixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, authInterface.Id),
|
FixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, authInterface.Id),
|
||||||
ReturnConfigList = await GetInterfaceReturnConfigListAsync(authInterface.Id),
|
ReturnConfigList = await GetInterfaceReturnConfigListAsync(authInterface.Id),
|
||||||
FormFieldList = await GetFormFieldListAsync(authInterface.Id),
|
FormFieldList = await GetFormFieldListAsync(authInterface.Id, FieldPosition.Body),
|
||||||
|
QueryFieldList = await GetFormFieldListAsync(authInterface.Id, FieldPosition.Query),
|
||||||
|
HeaderFieldList = await GetFormFieldListAsync(authInterface.Id, FieldPosition.Header),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inParaMaps = await GetParameterMapListAsync(mapIds, true);
|
|
||||||
foreach (var map in maps)
|
foreach (var map in maps)
|
||||||
{
|
{
|
||||||
var targetInterface = targetInterfaceList.First(x => map.DownStreamCode == x.Code);
|
var targetInterface = targetInterfaceList.First(x => map.DownStreamCode == x.Code);
|
||||||
|
var paraKind = targetInterface.ContentType == ContentType.FormUrlEncoded
|
||||||
|
? ParameterParaKind.MappingBody
|
||||||
|
: ParameterParaKind.Normal;
|
||||||
|
var inParaMaps = await GetParameterMapListAsync([map.Id], true, paraKind);
|
||||||
var items = inParaMaps.Where(x => x.InterfaceId == targetInterface.Id).ToList();
|
var items = inParaMaps.Where(x => x.InterfaceId == targetInterface.Id).ToList();
|
||||||
var fixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, targetInterface.Id);
|
var fixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, targetInterface.Id);
|
||||||
|
|
||||||
@ -235,17 +240,19 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
|||||||
ReturnConfigList = await GetInterfaceReturnConfigListAsync(targetInterface.Id),
|
ReturnConfigList = await GetInterfaceReturnConfigListAsync(targetInterface.Id),
|
||||||
PrefixScript = map.PrefixScript,
|
PrefixScript = map.PrefixScript,
|
||||||
PostfixScript = map.PostfixScript,
|
PostfixScript = map.PostfixScript,
|
||||||
FormFieldList = await GetFormFieldListAsync(targetInterface.Id),
|
FormFieldList = await GetFormFieldListAsync(targetInterface.Id, FieldPosition.Body),
|
||||||
|
QueryFieldList = await GetFormFieldListAsync(targetInterface.Id, FieldPosition.Query),
|
||||||
|
HeaderFieldList = await GetFormFieldListAsync(targetInterface.Id, FieldPosition.Header),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<InterfaceFormFieldDto>> GetFormFieldListAsync(int interfaceId)
|
private async Task<List<InterfaceFormFieldDto>> GetFormFieldListAsync(int interfaceId, FieldPosition fieldPosition)
|
||||||
{
|
{
|
||||||
return await Context.Queryable<FormParameterEntity>()
|
return await Context.Queryable<FormParameterEntity>()
|
||||||
.Where(x => x.InterfaceId == interfaceId)
|
.Where(x => x.InterfaceId == interfaceId && x.FieldPosition == fieldPosition)
|
||||||
.Select<InterfaceFormFieldDto>()
|
.Select<InterfaceFormFieldDto>()
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
@ -260,7 +267,7 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
|||||||
int interfaceId)
|
int interfaceId)
|
||||||
{
|
{
|
||||||
var fixedFieldList = await Context.Queryable<FixedParameterEntity>()
|
var fixedFieldList = await Context.Queryable<FixedParameterEntity>()
|
||||||
.Where(a => a.ServiceProviderId == serviceProviderId || a.InterfaceId == interfaceId)
|
.Where(a => a.ServiceProviderId == serviceProviderId)
|
||||||
.Select(x => new
|
.Select(x => new
|
||||||
{
|
{
|
||||||
x.ServiceProviderId,
|
x.ServiceProviderId,
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
namespace InterfaceForward.Repositories.Parameter.Entities;
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
|
|
||||||
|
namespace InterfaceForward.Repositories.Parameter.Entities;
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 表单参数
|
/// 表单参数
|
||||||
@ -30,6 +32,12 @@ public class FormParameterEntity : FullAuditedAggregateRoot<int, int>
|
|||||||
[SugarColumn(ColumnName = "Value")]
|
[SugarColumn(ColumnName = "Value")]
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 字段位置
|
||||||
|
///</summary>
|
||||||
|
[SugarColumn(ColumnName = "FieldPosition")]
|
||||||
|
public FieldPosition FieldPosition { get; set; }
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 参数描述
|
/// 参数描述
|
||||||
///</summary>
|
///</summary>
|
||||||
|
|||||||
@ -63,6 +63,12 @@ namespace InterfaceForward.Repositories.Interface.Entitys
|
|||||||
[SugarColumn(ColumnName = "IsInPara")]
|
[SugarColumn(ColumnName = "IsInPara")]
|
||||||
public bool IsInPara { get; set; }
|
public bool IsInPara { get; set; }
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// 参数用途:0普通;1映射体
|
||||||
|
///</summary>
|
||||||
|
[SugarColumn(ColumnName = "ParaKind")]
|
||||||
|
public ParameterParaKind ParaKind { get; set; }
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// 参数描述
|
/// 参数描述
|
||||||
///</summary>
|
///</summary>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using InterfaceForward.Repositories.Interface.Entitys;
|
using InterfaceForward.Repositories.Interface.Entitys;
|
||||||
using InterfaceForward.Repositories.Parameter.VO;
|
using InterfaceForward.Repositories.Parameter.VO;
|
||||||
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
|
|
||||||
namespace InterfaceForward.Repositories.Parameter.Services;
|
namespace InterfaceForward.Repositories.Parameter.Services;
|
||||||
|
|
||||||
@ -14,7 +15,8 @@ public interface IParameterRepository:IBasicRepository<ParameterEntity>
|
|||||||
/// <param name="interfaceId"></param>
|
/// <param name="interfaceId"></param>
|
||||||
/// <param name="isInPara"></param>
|
/// <param name="isInPara"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<InterfaceParameterOutputValueObject>> GetParameterListByNameAsync(int interfaceId, bool isInPara);
|
Task<List<InterfaceParameterOutputValueObject>> GetParameterListByNameAsync(int interfaceId, bool isInPara,
|
||||||
|
ParameterParaKind? paraKind = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存参数序列
|
/// 保存参数序列
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using InterfaceForward.Repositories.Interface.Entitys;
|
using InterfaceForward.Repositories.Interface.Entitys;
|
||||||
using InterfaceForward.Repositories.Parameter.VO;
|
using InterfaceForward.Repositories.Parameter.VO;
|
||||||
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
|
|
||||||
namespace InterfaceForward.Repositories.Parameter.Services;
|
namespace InterfaceForward.Repositories.Parameter.Services;
|
||||||
|
|
||||||
@ -10,11 +11,12 @@ public class ParameterRepository : BasicRepository<ParameterEntity>, IScopedDepe
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<List<InterfaceParameterOutputValueObject>> GetParameterListByNameAsync(int interfaceId,
|
public async Task<List<InterfaceParameterOutputValueObject>> GetParameterListByNameAsync(int interfaceId,
|
||||||
bool isInPara)
|
bool isInPara, ParameterParaKind? paraKind = null)
|
||||||
{
|
{
|
||||||
var query = Context.Queryable<ParameterEntity>()
|
var query = Context.Queryable<ParameterEntity>()
|
||||||
.Where(x => x.InterfaceId == interfaceId)
|
.Where(x => x.InterfaceId == interfaceId)
|
||||||
.Where(x => x.IsInPara == isInPara)
|
.Where(x => x.IsInPara == isInPara)
|
||||||
|
.WhereIF(paraKind != null, x => x.ParaKind == paraKind)
|
||||||
.OrderBy(x => x.Sort);
|
.OrderBy(x => x.Sort);
|
||||||
|
|
||||||
return await query.Select<InterfaceParameterOutputValueObject>().ToListAsync();
|
return await query.Select<InterfaceParameterOutputValueObject>().ToListAsync();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace InterfaceForward.Repositories.Parameter.VO
|
namespace InterfaceForward.Repositories.Parameter.VO
|
||||||
{
|
{
|
||||||
@ -34,6 +35,11 @@ namespace InterfaceForward.Repositories.Parameter.VO
|
|||||||
///</summary>
|
///</summary>
|
||||||
public int Type { get; set; }
|
public int Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参数用途
|
||||||
|
/// </summary>
|
||||||
|
public ParameterParaKind ParaKind { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否必填
|
/// 是否必填
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
using InterfaceForward.Application.Contracts.Dtos.ScriptAssistant;
|
using InterfaceForward.Application.Contracts.Dtos.ScriptAssistant;
|
||||||
|
using InterfaceForward.Application.Contracts.ForwardCore;
|
||||||
|
using InterfaceForward.Application.ForwardCore;
|
||||||
using InterfaceForward.Application.Services.ScriptAssistant;
|
using InterfaceForward.Application.Services.ScriptAssistant;
|
||||||
|
using InterfaceForward.Domain.Shared;
|
||||||
|
using InterfaceForward.Domain.Shared.Dtos;
|
||||||
|
using InterfaceForward.Domain.Shared.Enum;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace InterfaceForward.Application.Tests;
|
namespace InterfaceForward.Application.Tests;
|
||||||
@ -71,4 +76,57 @@ public class ScriptAssistantServiceTests
|
|||||||
|
|
||||||
Assert.Contains(output.Warnings, x => x.Contains("System.IO"));
|
Assert.Contains(output.Warnings, x => x.Contains("System.IO"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DefaultForwardFlowTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void SerializationBody_ShouldUseMappedInputForJson()
|
||||||
|
{
|
||||||
|
var flow = new TestForwardFlow();
|
||||||
|
var context = new ForwardCoreContext
|
||||||
|
{
|
||||||
|
TargetInterface = new InterfaceDto { ContentType = ContentType.Json },
|
||||||
|
OriginalInterfaceMappedInput = new JObject { ["orderId"] = "A001" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var body = flow.SerializationBody(context);
|
||||||
|
|
||||||
|
Assert.Equal("{\"orderId\":\"A001\"}", body);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetContentType_ShouldReplaceFromMappingBodyForFormUrlEncoded()
|
||||||
|
{
|
||||||
|
var flow = new TestForwardFlow();
|
||||||
|
var context = new ForwardCoreContext
|
||||||
|
{
|
||||||
|
TargetInterface = new InterfaceDto { ContentType = ContentType.FormUrlEncoded },
|
||||||
|
TargetInterfaceInput = "{\"orderId\":\"A001\"}",
|
||||||
|
OriginalInterfaceMappedInput = new JObject { ["orderId"] = "A001" },
|
||||||
|
FormFieldList =
|
||||||
|
[
|
||||||
|
new InterfaceFormFieldDto
|
||||||
|
{
|
||||||
|
Name = "notifyBizEventDTO",
|
||||||
|
Value = GlobalConst.FromMappingBody
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
using var message = new HttpRequestMessage();
|
||||||
|
flow.SetContentTypeForTest(context, message);
|
||||||
|
|
||||||
|
var content = await message.Content!.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Assert.Equal("notifyBizEventDTO=%7B%22orderId%22%3A%22A001%22%7D", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestForwardFlow : DefaultForwardFlow
|
||||||
|
{
|
||||||
|
public void SetContentTypeForTest(ForwardCoreContext context, HttpRequestMessage message)
|
||||||
|
{
|
||||||
|
SetContentType(context, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
372
方案B-重构清单-前后对比.md
Normal file
372
方案B-重构清单-前后对比.md
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
# 方案 B 重构清单(前后对比 · 修订版)
|
||||||
|
|
||||||
|
> **前提**:全量重构,不做旧字段兼容。
|
||||||
|
> **修订要点**:先定义「一次 HTTP 请求」应保存哪些结构,再说明 **Mapping Body 仅在某些 Content-Type 下才存在**;`application/json` 的请求体参数树 **本身就是映射体**,不单独拆 Mapping Body。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 设计顺序(先看这个)
|
||||||
|
|
||||||
|
```text
|
||||||
|
第一步 请求接口应保存什么(与 Content-Type 无关 + 有关部分分开)
|
||||||
|
Query / Header / Body 传输层 + 响应 + 基本信息
|
||||||
|
|
||||||
|
第二步 映射体放哪(由 Content-Type 决定)
|
||||||
|
Json/Xml → Body 参数树 = 映射体
|
||||||
|
Form 类 → 传输用表单 KV + 独立 Mapping Body 树(表单字段可 $FromMappingBody)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mapping Body 不是每个接口都有**,只有「Body(或 Query)走表单 KV,且业务 JSON 需要单独做上游映射」时才配置。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 改造后:一次请求应保存什么(目标模型)
|
||||||
|
|
||||||
|
### 2.1 与 Content-Type **无关**(任何下游接口都有)
|
||||||
|
|
||||||
|
| 存储 | 表 | UI(对齐 ApiTest) | 说明 |
|
||||||
|
|------|-----|-------------------|------|
|
||||||
|
| **基本信息** | `t_interface` | 地址、Method、Protocol、ContentType、QPS… | 不变 |
|
||||||
|
| **Query** | `t_parameter_form`(FieldPosition=**Query**) | Query Tab,KV | 真实 URL Query,不仅 FormUrlEncoded 才有 |
|
||||||
|
| **Header** | `t_parameter_form`(FieldPosition=**Header**) | Header Tab,KV | 请求头;占位符 $TimeStamp、$token 等 |
|
||||||
|
| **Response** | `t_parameter`(IsInPara=false) | Response 参数树 | 不变 |
|
||||||
|
| **返回配置** | `t_interface_return_config` | 返回配置 Tab | 不变 |
|
||||||
|
| **cURL 示例** | `t_interface.InParams` | cURL Tab | 不变 |
|
||||||
|
| **服务商级 Fixed** | `t_parameter_fixed`(ServiceProviderId) | 不在接口明细维护 | Url 占位、服务商通用 Header、脚本写入 |
|
||||||
|
|
||||||
|
### 2.2 与 Content-Type **有关**(Body 区不同)
|
||||||
|
|
||||||
|
| ContentType | Body 传输层保存什么 | 映射体保存什么 | 是否需要 Mapping Body |
|
||||||
|
|-------------|---------------------|----------------|------------------------|
|
||||||
|
| **Json (3)** | **`requestBodyParameterList`** 参数树 | **同一棵树** | **否** |
|
||||||
|
| **Xml (4)** | **`requestBodyParameterList`** 参数树 | **同一棵树** | **否** |
|
||||||
|
| **FormUrlEncoded (1)** | **`bodyFormParameterList`** KV | **`mappingBodyParameterList`** 参数树 | **是** |
|
||||||
|
| **FormData (2)** | 二期:`bodyForm` 或 multipart 描述 | 若字段内嵌 JSON,同 FormUrlEncoded | 二期 |
|
||||||
|
| **上游接口** | **`inParameterList`** 树(业务入参) | **同一棵树** | **否** |
|
||||||
|
|
||||||
|
### 2.3 结构总图(改造后)
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌─ 基本信息 (t_interface)
|
||||||
|
│
|
||||||
|
任意 Content-Type ├─ queryFormParameterList (t_parameter_form, Query)
|
||||||
|
├─ headerFormParameterList (t_parameter_form, Header)
|
||||||
|
│
|
||||||
|
├─ Body 区 ─────────────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ Json/Xml FormUrlEncoded │
|
||||||
|
│ requestBody bodyFormParameterList │
|
||||||
|
│ ParameterList (KV 传输) │
|
||||||
|
│ (树=映射体) mappingBodyParameterList │
|
||||||
|
│ (树=仅映射体) │
|
||||||
|
└────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
├─ outParameterList (出参树)
|
||||||
|
└─ inParams (cURL 示例)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 页面 Tab(下游接口 · 按 Content-Type 显示)
|
||||||
|
|
||||||
|
| Tab | Json / Xml | FormUrlEncoded |
|
||||||
|
|-----|------------|----------------|
|
||||||
|
| Query | 显示 KV | 显示 KV |
|
||||||
|
| Header | 显示 KV | 显示 KV |
|
||||||
|
| **Body** | **参数树**(= 映射体) | **KV 表**(传输) |
|
||||||
|
| **Mapping Body** | **隐藏** | **显示**(参数树) |
|
||||||
|
| cURL | 显示 | 显示 |
|
||||||
|
| Response | 显示 | 显示 |
|
||||||
|
| ~~固定配置~~ | 删除(接口级) | 删除 |
|
||||||
|
|
||||||
|
与 ApiTest 对齐方式:
|
||||||
|
|
||||||
|
- ApiTest 的 Request Tab:Json 时常用 Raw;**接口配置**里 Json 仍用 **参数树** 定义结构(itfx 现有能力,且即映射体)。
|
||||||
|
- ApiTest 的 FormUrlEncoded:URL Encoded KV = 我们的 **bodyForm**;映射结构不在调试页里,在接口配置里用 **Mapping Body** 维护。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Mapping Body 何时存在(规则定稿)
|
||||||
|
|
||||||
|
| 条件 | 结论 |
|
||||||
|
|------|------|
|
||||||
|
| `ContentType = Json` 或 `Xml` | **没有** `mappingBodyParameterList`;`requestBodyParameterList` 参与 `InParamRestructure` 且被 `SerializationBody` 序列化 |
|
||||||
|
| `ContentType = FormUrlEncoded` | **有** `bodyFormParameterList` + **有** `mappingBodyParameterList`;映射只对 Mapping Body 树;表单字段值可为 `$FromMappingBody` |
|
||||||
|
| Query 上也有「值为 JSON」的罕见情况 | 仍用 Mapping Body 树做映射,Query KV 里字段填 `$FromMappingBody`(与 Body 表单同理) |
|
||||||
|
| 上游 `IsUpStream=true` | 始终只有 **`inParameterList`**,无 Mapping Body、无 bodyForm |
|
||||||
|
|
||||||
|
**占位符**
|
||||||
|
|
||||||
|
| 占位符 | 用于 | Content-Type |
|
||||||
|
|--------|------|----------------|
|
||||||
|
| `$FromMappingBody` | Form 的 Query/Body(及必要时 Header)字段引用映射结果 | **仅 Form 类** |
|
||||||
|
| `$FromBody` | **删除**下游表单中的用法 | — |
|
||||||
|
| Json Body 树字段 | 直接映射到 alias,**不需要**占位符塞整段 JSON | Json / Xml |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 数据库(修订)
|
||||||
|
|
||||||
|
### 4.1 `t_parameter_form` — 传输层 KV
|
||||||
|
|
||||||
|
**新增** `FieldPosition`:Header=1, Body=2, Query=3。
|
||||||
|
|
||||||
|
| FieldPosition | 何时有数据 |
|
||||||
|
|---------------|------------|
|
||||||
|
| Query | 任意 Content-Type,有 URL 参数就配 |
|
||||||
|
| Header | 任意 Content-Type |
|
||||||
|
| Body | **主要 FormUrlEncoded**;Json/Xml 通常 **无 body 行**(Body 在参数树) |
|
||||||
|
|
||||||
|
### 4.2 `t_parameter` — 参数树
|
||||||
|
|
||||||
|
**新增** `ParaKind`:
|
||||||
|
|
||||||
|
| ParaKind | 含义 | 用于 |
|
||||||
|
|----------|------|------|
|
||||||
|
| **0 Normal** | 默认 | 出参;**上游入参**;Json/Xml 的 **RequestBody** |
|
||||||
|
| **1 MappingBody** | 仅映射、不直接当 HTTP Json Body | **仅** FormUrlEncoded(及日后 FormData)且需要独立映射体时 |
|
||||||
|
|
||||||
|
| 列表字段 | ParaKind | IsInPara |
|
||||||
|
|----------|----------|----------|
|
||||||
|
| `requestBodyParameterList` | Normal(或枚举值 RequestBody=0) | true |
|
||||||
|
| `mappingBodyParameterList` | **MappingBody** | true |
|
||||||
|
| `outParameterList` | Normal | false |
|
||||||
|
|
||||||
|
**删除的用法**
|
||||||
|
|
||||||
|
- 不再用「一棵 in 树」同时表示 Form 映射 + Json Body(改造前混用)。
|
||||||
|
|
||||||
|
### 4.3 `t_parameter_fixed`
|
||||||
|
|
||||||
|
- **删**:接口明细维护接口级 Header/Query/Body KV。
|
||||||
|
- **留**:服务商级、Url、脚本动态 Header。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. SaveInterface / GetInterfaceById(请求结构)
|
||||||
|
|
||||||
|
`POST /api/Interface/SaveInterface` · 响应为接口 `id`(number)。
|
||||||
|
`GetInterfaceById` 字段与保存一致。已删除:`formParameterList`、下游 `inParameterList`。
|
||||||
|
|
||||||
|
### 5.1 根对象
|
||||||
|
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `optionType` | `1` 增 / `3` 改 / `2` 删 |
|
||||||
|
| `isUpStream` | `true` 上游 / `false` 下游 |
|
||||||
|
| `serviceProviderId` | 上游 `0` |
|
||||||
|
| `id` | 改、删必填 |
|
||||||
|
| `name`, `requestAddress`, `requestProtocol`, `requestMethod`, `contentType` | 基本信息 |
|
||||||
|
| `code`, `category`, `description`, `isBatch`, `limit`, `responseContentType`, `flowCode`, `isDisableAuth`, `qps`, `mappedParamType`, `inParams` | 可选 |
|
||||||
|
| `queryFormParameterList` | Query KV,`fieldPosition=3` |
|
||||||
|
| `headerFormParameterList` | Header KV,`fieldPosition=1` |
|
||||||
|
| `outParameterList` | 出参树 |
|
||||||
|
| `requestBodyParameterList` | **仅下游 Json/Xml**,Body 树 = 映射体 |
|
||||||
|
| `bodyFormParameterList` | **仅下游 FormUrlEncoded**,Body KV |
|
||||||
|
| `mappingBodyParameterList` | **仅下游 FormUrlEncoded**,映射树 |
|
||||||
|
| `inParameterList` | **仅上游**入参树 |
|
||||||
|
|
||||||
|
### 5.2 Body 字段互斥
|
||||||
|
|
||||||
|
| 场景 | 传 | 不传 |
|
||||||
|
|------|-----|------|
|
||||||
|
| 下游 Json/Xml (`contentType` 3/4) | `requestBodyParameterList` | `bodyForm*`、`mappingBody*`、`inParameterList` |
|
||||||
|
| 下游 FormUrlEncoded (`1`) | `bodyFormParameterList` + `mappingBodyParameterList` | `requestBody*`、`inParameterList` |
|
||||||
|
| 上游 | `inParameterList` | `requestBody*`、`bodyForm*`、`mappingBody*` |
|
||||||
|
|
||||||
|
### 5.3 子结构
|
||||||
|
|
||||||
|
**FormParameterInput**(Query / Header / Body 行)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "optionType": 1, "id": 0, "name": "字段名", "value": "$FromMappingBody", "description": "", "fieldPosition": 2 }
|
||||||
|
```
|
||||||
|
|
||||||
|
`fieldPosition`:`1` Header · `2` Body · `3` Query。Form 业务 JSON 字段用 `$FromMappingBody`。
|
||||||
|
|
||||||
|
**ParameterInput**(树节点:requestBody / mappingBody / in / out)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "optionType": 1, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "isRequired": true, "sort": "1", "paraKind": 0 }
|
||||||
|
```
|
||||||
|
|
||||||
|
`paraKind`:`0` Normal(requestBody、上游 in、出参)· `1` MappingBody(仅 mappingBody 列表)。新增时 `id`/`pId` 需表达父子关系。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5.4 示例
|
||||||
|
|
||||||
|
**下游 · Json**(`contentType: 3`)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"optionType": 1,
|
||||||
|
"isUpStream": false,
|
||||||
|
"serviceProviderId": 5,
|
||||||
|
"name": "创建订单",
|
||||||
|
"requestAddress": "https://api.example.com/order",
|
||||||
|
"requestProtocol": 2,
|
||||||
|
"requestMethod": 2,
|
||||||
|
"contentType": 3,
|
||||||
|
"queryFormParameterList": [
|
||||||
|
{ "optionType": 1, "id": 0, "name": "access_token", "value": "$FromAccount", "fieldPosition": 3 }
|
||||||
|
],
|
||||||
|
"headerFormParameterList": [],
|
||||||
|
"requestBodyParameterList": [
|
||||||
|
{ "optionType": 1, "id": 1, "pId": 0, "name": "orderId", "alias": "orderId", "type": 1, "paraKind": 0 }
|
||||||
|
],
|
||||||
|
"outParameterList": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**下游 · FormUrlEncoded**(`contentType: 1`)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"optionType": 3,
|
||||||
|
"isUpStream": false,
|
||||||
|
"serviceProviderId": 5,
|
||||||
|
"id": 1001,
|
||||||
|
"name": "1688回调",
|
||||||
|
"requestAddress": "https://gw.open.1688.com/openapi/http",
|
||||||
|
"requestProtocol": 2,
|
||||||
|
"requestMethod": 2,
|
||||||
|
"contentType": 1,
|
||||||
|
"queryFormParameterList": [
|
||||||
|
{ "optionType": 3, "id": 11, "name": "_aop_timestamp", "value": "$TimeStamp", "description": "ms", "fieldPosition": 3 }
|
||||||
|
],
|
||||||
|
"headerFormParameterList": [],
|
||||||
|
"bodyFormParameterList": [
|
||||||
|
{ "optionType": 3, "id": 10, "name": "notifyBizEventDTO", "value": "$FromMappingBody", "fieldPosition": 2 },
|
||||||
|
{ "optionType": 3, "id": 13, "name": "_aop_signature", "value": "", "fieldPosition": 2 }
|
||||||
|
],
|
||||||
|
"mappingBodyParameterList": [
|
||||||
|
{ "optionType": 3, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "paraKind": 1 },
|
||||||
|
{ "optionType": 3, "id": 2, "pId": 1, "name": "orderId", "alias": "orderId", "type": 1, "paraKind": 1 }
|
||||||
|
],
|
||||||
|
"outParameterList": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**上游**(`isUpStream: true`)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"optionType": 1,
|
||||||
|
"isUpStream": true,
|
||||||
|
"serviceProviderId": 0,
|
||||||
|
"name": "标准创建订单",
|
||||||
|
"requestAddress": "/api/order/create",
|
||||||
|
"requestProtocol": 2,
|
||||||
|
"requestMethod": 2,
|
||||||
|
"contentType": 3,
|
||||||
|
"queryFormParameterList": [],
|
||||||
|
"headerFormParameterList": [],
|
||||||
|
"inParameterList": [
|
||||||
|
{ "optionType": 1, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "paraKind": 0 }
|
||||||
|
],
|
||||||
|
"outParameterList": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 转发逻辑(修订)
|
||||||
|
|
||||||
|
### 6.1 映射树来源(InParamTreeList)
|
||||||
|
|
||||||
|
| ContentType | InParamTreeList 来源 |
|
||||||
|
|-------------|----------------------|
|
||||||
|
| Json / Xml | **`requestBodyParameterList`**(整棵树) |
|
||||||
|
| FormUrlEncoded | **`mappingBodyParameterList`** |
|
||||||
|
| 上游 | 系统接口 **inParameterList**(映射配置页不变) |
|
||||||
|
|
||||||
|
### 6.2 HTTP 组装
|
||||||
|
|
||||||
|
| 部分 | 来源 |
|
||||||
|
|------|------|
|
||||||
|
| URL Query | `queryFormParameterList`(+ 服务商 Fixed Query) |
|
||||||
|
| Header | `headerFormParameterList`(+ 服务商 Fixed Header) |
|
||||||
|
| Body Json | `Serialize(requestBodyParameterList` 映射结果 `)` |
|
||||||
|
| Body FormUrlEncoded | 仅 **`bodyFormParameterList`**;其中 `$FromMappingBody` ← 映射结果序列化 |
|
||||||
|
| Body Xml | 同 Json,Xml 序列化 |
|
||||||
|
|
||||||
|
### 6.3 流程对比(两张)
|
||||||
|
|
||||||
|
**Json 下游(无 Mapping Body)**
|
||||||
|
|
||||||
|
```text
|
||||||
|
上游 JSON → Restructure(requestBodyParameterList) → OriginalInterfaceMappedInput
|
||||||
|
→ ReplacePlaceholder(Query/Header form + Fixed)
|
||||||
|
→ SerializationBody(Json) → HTTP Body
|
||||||
|
→ 拼 Query / Header
|
||||||
|
```
|
||||||
|
|
||||||
|
**FormUrlEncoded 下游(有 Mapping Body)**
|
||||||
|
|
||||||
|
```text
|
||||||
|
上游 JSON → Restructure(mappingBodyParameterList) → OriginalInterfaceMappedInput
|
||||||
|
→ ReplacePlaceholder(含 bodyForm 的 $FromMappingBody)
|
||||||
|
→ bodyForm 字典 → HTTP Body
|
||||||
|
→ 拼 Query / Header
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 前后对比总表(增删改)
|
||||||
|
|
||||||
|
### 7.1 删除了什么
|
||||||
|
|
||||||
|
| 类别 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| API | 下游 `formParameterList`、下游笼统的 `inParameterList`(拆开后互斥) |
|
||||||
|
| UI | 固定配置 Tab;接口级 Fixed API |
|
||||||
|
| 语义 | 所有下游共用一棵 in 树;Form 无 position;Json 也搞 Mapping Body Tab |
|
||||||
|
| 占位 | 下游表单用 `$FromBody` 表示整段 JSON |
|
||||||
|
|
||||||
|
### 7.2 新增了什么
|
||||||
|
|
||||||
|
| 类别 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| 表 | `t_parameter_form.FieldPosition`;`t_parameter.ParaKind` |
|
||||||
|
| API | `queryFormParameterList`、`headerFormParameterList`(**全类型共有**) |
|
||||||
|
| API | `bodyFormParameterList`(**仅 Form 类**) |
|
||||||
|
| API | `requestBodyParameterList`(**仅 Json/Xml**,=映射体) |
|
||||||
|
| API | `mappingBodyParameterList`(**仅 Form 类**) |
|
||||||
|
| UI | Header Tab;Form 时 Mapping Body Tab;Json 时 Body=树 |
|
||||||
|
| 占位 | `$FromMappingBody`(**仅 Form KV**) |
|
||||||
|
|
||||||
|
### 7.3 改了什么
|
||||||
|
|
||||||
|
| 项 | 改造前 | 改造后 |
|
||||||
|
|----|--------|--------|
|
||||||
|
| Query | 假 Query(实为 form body) | 真 Query KV,**所有 Content-Type** |
|
||||||
|
| Body Tab | 永远是参数树 | **Json=树**;**Form=KV** |
|
||||||
|
| 映射体 | 永远 in 树 | **Json=Body 树**;**Form=Mapping Body 树** |
|
||||||
|
| 保存 | form + in 混传 | 按 ContentType 传 **互斥** 的 Body 相关列表 |
|
||||||
|
| 映射 SQL | 下游 IsInPara 全量 | Json:RequestBody 树;Form:**ParaKind=MappingBody** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Content-Type 全量对照(改造后)
|
||||||
|
|
||||||
|
| ContentType | queryForm | headerForm | bodyForm | requestBody 树 | mappingBody 树 | 映射目标 | HTTP Body |
|
||||||
|
|-------------|-----------|------------|----------|----------------|----------------|----------|-----------|
|
||||||
|
| **Json** | 可选 | 可选 | **不用** | **必填** | **不用** | requestBody 树 | 序列化该树 |
|
||||||
|
| **Xml** | 可选 | 可选 | **不用** | **必填** | **不用** | requestBody 树 | Xml 序列化 |
|
||||||
|
| **FormUrlEncoded** | 常用 | 常用 | **必填** | **不用** | **必填** | mappingBody 树 | bodyForm 字典 |
|
||||||
|
| **FormData** | 二期 | 二期 | 二期 | **不用** | 二期 | 二期 | 二期 |
|
||||||
|
| **上游 Json** | — | — | — | **inParameterList** | — | in 树 | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 一句话
|
||||||
|
|
||||||
|
| | 改造前 | 改造后 |
|
||||||
|
|---|--------|--------|
|
||||||
|
| 先保存什么 | form + in 混在一起 | **先** Query/Header(通用)+ **再按 Content-Type 存 Body** |
|
||||||
|
| Json | in 树 = 映射 + Body | **requestBody 树 = 映射体**,不要 Mapping Body |
|
||||||
|
| Form | in 树 + form 表 | **bodyForm 传输** + **mappingBody 映射** |
|
||||||
|
| Mapping Body | (之前文档)每个下游都有 | **仅 Form 类需要** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档版本:2026-06-02 · 含 SaveInterface 结构与示例(§5)*
|
||||||
Loading…
Reference in New Issue
Block a user